Merge tag 'gpio-for-linus' of git://git.secretlab.ca/git/linux-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 11 Dec 2012 21:00:56 +0000 (13:00 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 11 Dec 2012 21:00:56 +0000 (13:00 -0800)
Pull GPIO updates from Grant Likely:
 "GPIO follow up patch and type change for v3.5 merge window

  Primarily device driver additions, features and bug fixes.  Not much
  touching gpio common subsystem support.  Should not be scary."

* tag 'gpio-for-linus' of git://git.secretlab.ca/git/linux-2.6: (34 commits)
  gpio: Provide the STMPE GPIO driver with its own IRQ Domain
  gpio: add TS-5500 DIO blocks support
  gpio: pcf857x: use client->irq for gpio_to_irq()
  gpio: stmpe: Add DT support for stmpe gpio
  gpio: pl061 depends on ARM
  gpio/pl061: remove old comment
  gpio: SPEAr: add spi chipselect control driver
  gpio: gpio-max710x: Support device tree probing
  gpio: twl4030: Use only TWL4030_MODULE_LED for LED configuration
  gpio: tegra: read output value when gpio is set in direction_out
  gpio: pca953x: Add compatible strings to gpio-pca953x driver
  gpio: pca953x: Register an IRQ domain
  gpio: mvebu: Set free callback for gpio_chip
  gpio: tegra: Drop exporting static functions
  gpio: tegra: Staticize non-exported symbols
  gpio: tegra: fix suspend/resume apis
  gpio-pch: Set parent dev for gpio chip
  gpio: em: Fix build errors
  GPIO: clps711x: use platform_device_unregister in gpio_clps711x_init()
  gpio/tc3589x: convert to use the simple irqdomain
  ...

2251 files changed:
.gitignore
CREDITS
Documentation/00-INDEX
Documentation/ABI/testing/sysfs-class-devfreq
Documentation/ABI/testing/sysfs-devices-power
Documentation/ABI/testing/sysfs-devices-sun [new file with mode: 0644]
Documentation/DocBook/media/Makefile
Documentation/DocBook/networking.tmpl
Documentation/IPMI.txt
Documentation/IRQ-domain.txt
Documentation/acpi/enumeration.txt [new file with mode: 0644]
Documentation/arm64/memory.txt
Documentation/cgroups/memory.txt
Documentation/devicetree/bindings/arm/atmel-at91.txt
Documentation/devicetree/bindings/arm/davinci/nand.txt
Documentation/devicetree/bindings/arm/l2cc.txt
Documentation/devicetree/bindings/clock/imx23-clock.txt
Documentation/devicetree/bindings/clock/imx28-clock.txt
Documentation/devicetree/bindings/cpufreq/cpufreq-spear.txt [new file with mode: 0644]
Documentation/devicetree/bindings/gpio/gpio.txt
Documentation/devicetree/bindings/gpio/gpio_atmel.txt
Documentation/devicetree/bindings/i2c/i2c-at91.txt [moved from Documentation/devicetree/bindings/i2c/atmel-i2c.txt with 100% similarity]
Documentation/devicetree/bindings/i2c/i2c-davinci.txt [moved from Documentation/devicetree/bindings/i2c/davinci.txt with 100% similarity]
Documentation/devicetree/bindings/i2c/i2c-gpio.txt [moved from Documentation/devicetree/bindings/i2c/gpio-i2c.txt with 100% similarity]
Documentation/devicetree/bindings/i2c/i2c-imx.txt [moved from Documentation/devicetree/bindings/i2c/fsl-imx-i2c.txt with 100% similarity]
Documentation/devicetree/bindings/i2c/i2c-mpc.txt [moved from Documentation/devicetree/bindings/i2c/fsl-i2c.txt with 100% similarity]
Documentation/devicetree/bindings/i2c/i2c-mux.txt [moved from Documentation/devicetree/bindings/i2c/mux.txt with 100% similarity]
Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt [new file with mode: 0644]
Documentation/devicetree/bindings/i2c/i2c-nomadik.txt [moved from Documentation/devicetree/bindings/i2c/nomadik.txt with 100% similarity]
Documentation/devicetree/bindings/i2c/i2c-octeon.txt [moved from Documentation/devicetree/bindings/i2c/cavium-i2c.txt with 100% similarity]
Documentation/devicetree/bindings/i2c/i2c-omap.txt [moved from Documentation/devicetree/bindings/i2c/omap-i2c.txt with 100% similarity]
Documentation/devicetree/bindings/i2c/i2c-pnx.txt [moved from Documentation/devicetree/bindings/i2c/pnx.txt with 100% similarity]
Documentation/devicetree/bindings/i2c/i2c-pxa-pci-ce4100.txt [moved from Documentation/devicetree/bindings/i2c/ce4100-i2c.txt with 100% similarity]
Documentation/devicetree/bindings/i2c/i2c-pxa.txt [moved from Documentation/devicetree/bindings/i2c/mrvl-i2c.txt with 70% similarity]
Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt [moved from Documentation/devicetree/bindings/i2c/samsung-i2c.txt with 100% similarity]
Documentation/devicetree/bindings/i2c/i2c-sirf.txt [moved from Documentation/devicetree/bindings/i2c/sirf-i2c.txt with 100% similarity]
Documentation/devicetree/bindings/i2c/i2c-versatile.txt [moved from Documentation/devicetree/bindings/i2c/arm-versatile.txt with 100% similarity]
Documentation/devicetree/bindings/i2c/i2c-xiic.txt [moved from Documentation/devicetree/bindings/i2c/xiic.txt with 100% similarity]
Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt [new file with mode: 0644]
Documentation/devicetree/bindings/leds/common.txt [new file with mode: 0644]
Documentation/devicetree/bindings/leds/leds-gpio.txt [moved from Documentation/devicetree/bindings/gpio/led.txt with 68% similarity]
Documentation/devicetree/bindings/mmc/mmc.txt
Documentation/devicetree/bindings/mmc/samsung-sdhci.txt
Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt [moved from Documentation/devicetree/bindings/mmc/synposis-dw-mshc.txt with 100% similarity]
Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
Documentation/devicetree/bindings/mmc/vt8500-sdmmc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/net/mdio-gpio.txt
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/rtc/orion-rtc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/devicetree/usage-model.txt
Documentation/filesystems/proc.txt
Documentation/firmware_class/README
Documentation/gpio.txt
Documentation/hwmon/ads7828
Documentation/hwmon/coretemp
Documentation/hwmon/da9055 [new file with mode: 0644]
Documentation/hwmon/fam15h_power
Documentation/hwmon/submitting-patches
Documentation/kbuild/makefiles.txt
Documentation/mmc/mmc-dev-attrs.txt
Documentation/networking/netdev-features.txt
Documentation/networking/vxlan.txt
Documentation/pinctrl.txt
Documentation/power/pm_qos_interface.txt
Documentation/sysrq.txt
Documentation/zh_CN/IRQ.txt [new file with mode: 0644]
Documentation/zh_CN/arm64/booting.txt [new file with mode: 0644]
Documentation/zh_CN/arm64/memory.txt [new file with mode: 0644]
MAINTAINERS
Makefile
arch/alpha/include/asm/thread_info.h
arch/alpha/kernel/osf_sys.c
arch/alpha/kernel/process.c
arch/alpha/kernel/traps.c
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/boot/Makefile
arch/arm/boot/compressed/head.S
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/animeo_ip.dts [new file with mode: 0644]
arch/arm/boot/dts/at91rm9200.dtsi [new file with mode: 0644]
arch/arm/boot/dts/at91rm9200ek.dts [new file with mode: 0644]
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_2mmc.dts
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/at91sam9n12ek.dts
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/dbx5x0.dtsi
arch/arm/boot/dts/dove.dtsi
arch/arm/boot/dts/exynos4210-trats.dts
arch/arm/boot/dts/imx23.dtsi
arch/arm/boot/dts/imx28.dtsi
arch/arm/boot/dts/imx6q-arm2.dts
arch/arm/boot/dts/kirkwood-lsxl.dtsi
arch/arm/boot/dts/omap3.dtsi
arch/arm/boot/dts/pm9g45.dts [new file with mode: 0644]
arch/arm/boot/dts/spear1310-evb.dts
arch/arm/boot/dts/spear1310.dtsi
arch/arm/boot/dts/spear1340-evb.dts
arch/arm/boot/dts/spear1340.dtsi
arch/arm/boot/dts/spear310.dtsi
arch/arm/boot/dts/spear320-evb.dts
arch/arm/boot/dts/spear320.dtsi
arch/arm/boot/dts/tegra20-seaboard.dts
arch/arm/boot/dts/tegra30.dtsi
arch/arm/boot/dts/wm8505.dtsi
arch/arm/common/timer-sp.c
arch/arm/configs/at91_dt_defconfig
arch/arm/configs/imx_v6_v7_defconfig
arch/arm/configs/mvebu_defconfig
arch/arm/configs/versatile_defconfig
arch/arm/include/asm/flat.h
arch/arm/include/asm/hardware/sp810.h
arch/arm/include/asm/io.h
arch/arm/include/asm/prom.h
arch/arm/include/asm/sched_clock.h
arch/arm/include/asm/uaccess.h
arch/arm/include/asm/vfpmacros.h
arch/arm/include/asm/xen/interface.h
arch/arm/include/asm/xen/page.h
arch/arm/include/debug/8250_32.S [new file with mode: 0644]
arch/arm/include/debug/picoxcell.S
arch/arm/include/debug/socfpga.S
arch/arm/include/uapi/asm/hwcap.h
arch/arm/kernel/entry-common.S
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/sched_clock.c
arch/arm/kernel/smp.c
arch/arm/kernel/smp_twd.c
arch/arm/lib/delay.c
arch/arm/mach-at91/Kconfig
arch/arm/mach-at91/Makefile
arch/arm/mach-at91/at91rm9200.c
arch/arm/mach-at91/at91rm9200_devices.c
arch/arm/mach-at91/at91rm9200_time.c
arch/arm/mach-at91/at91sam9260.c
arch/arm/mach-at91/at91sam9260_devices.c
arch/arm/mach-at91/at91sam9261.c
arch/arm/mach-at91/at91sam9261_devices.c
arch/arm/mach-at91/at91sam9263.c
arch/arm/mach-at91/at91sam9263_devices.c
arch/arm/mach-at91/at91sam9g45.c
arch/arm/mach-at91/at91sam9g45_devices.c
arch/arm/mach-at91/at91sam9n12.c
arch/arm/mach-at91/at91sam9rl.c
arch/arm/mach-at91/at91sam9rl_devices.c
arch/arm/mach-at91/at91sam9x5.c
arch/arm/mach-at91/at91x40.c
arch/arm/mach-at91/board-dt.c
arch/arm/mach-at91/board-neocore926.c
arch/arm/mach-at91/board-rm9200-dt.c [new file with mode: 0644]
arch/arm/mach-at91/board-sam9261ek.c
arch/arm/mach-at91/board-sam9263ek.c
arch/arm/mach-at91/generic.h
arch/arm/mach-at91/gpio.c
arch/arm/mach-at91/include/mach/board.h
arch/arm/mach-at91/irq.c
arch/arm/mach-at91/setup.c
arch/arm/mach-at91/soc.h
arch/arm/mach-davinci/dm644x.c
arch/arm/mach-dove/common.c
arch/arm/mach-dove/include/mach/pm.h
arch/arm/mach-dove/irq.c
arch/arm/mach-dove/pcie.c
arch/arm/mach-exynos/common.c
arch/arm/mach-exynos/dma.c
arch/arm/mach-exynos/include/mach/map.h
arch/arm/mach-exynos/mach-exynos4-dt.c
arch/arm/mach-highbank/system.c
arch/arm/mach-imx/clk-busy.c
arch/arm/mach-imx/clk-gate2.c
arch/arm/mach-imx/clk-imx25.c
arch/arm/mach-imx/clk-imx27.c
arch/arm/mach-imx/ehci-imx25.c
arch/arm/mach-imx/ehci-imx35.c
arch/arm/mach-imx/mm-imx3.c
arch/arm/mach-integrator/impd1.c
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-kirkwood/pcie.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-omap1/board-ams-delta.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/board-igep0020.c
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-omap2/clock33xx_data.c
arch/arm/mach-omap2/clock44xx_data.c
arch/arm/mach-omap2/clockdomain.c
arch/arm/mach-omap2/clockdomains44xx_data.c
arch/arm/mach-omap2/common-board-devices.c
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/mux34xx.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/pm.h
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/serial.c
arch/arm/mach-omap2/timer.c
arch/arm/mach-omap2/twl-common.c
arch/arm/mach-omap2/vc.c
arch/arm/mach-prima2/include/mach/gpio.h [deleted file]
arch/arm/mach-pxa/hx4700.c
arch/arm/mach-pxa/spitz_pm.c
arch/arm/mach-s3c24xx/clock-s3c2440.c
arch/arm/mach-s3c24xx/s3c2416.c
arch/arm/mach-s3c24xx/s3c2443.c
arch/arm/mach-s5p64x0/common.c
arch/arm/mach-s5pc100/common.c
arch/arm/mach-s5pv210/common.c
arch/arm/mach-shmobile/board-armadillo800eva.c
arch/arm/mach-shmobile/clock-r8a7779.c
arch/arm/mach-shmobile/setup-r8a7779.c
arch/arm/mach-spear13xx/include/mach/spear1310_misc_regs.h [deleted file]
arch/arm/mach-spear13xx/include/mach/spear1340_misc_regs.h [deleted file]
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/tegra20_clocks_data.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/cpu.c
arch/arm/mach-ux500/devices-common.c
arch/arm/mach-ux500/devices-common.h
arch/arm/mach-vexpress/v2m.c
arch/arm/mm/alignment.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/proc-v6.S
arch/arm/mm/vmregion.h
arch/arm/plat-mxc/devices/platform-mxc-mmc.c
arch/arm/plat-nomadik/include/plat/gpio-nomadik.h [deleted file]
arch/arm/plat-omap/Kconfig
arch/arm/plat-omap/debug-devices.c
arch/arm/plat-omap/i2c.c
arch/arm/plat-omap/include/plat/mmc.h
arch/arm/plat-omap/include/plat/omap-serial.h
arch/arm/plat-omap/include/plat/omap_hwmod.h
arch/arm/plat-s3c24xx/dma.c
arch/arm/plat-samsung/include/plat/spi-core.h [new file with mode: 0644]
arch/arm/tools/Makefile
arch/arm/vfp/vfpmodule.c
arch/arm/xen/enlighten.c
arch/arm/xen/grant-table.c
arch/arm/xen/hypercall.S
arch/arm64/Kconfig
arch/arm64/Makefile
arch/arm64/boot/Makefile
arch/arm64/boot/dts/.gitignore [new file with mode: 0644]
arch/arm64/boot/dts/Makefile [new file with mode: 0644]
arch/arm64/include/asm/Kbuild
arch/arm64/include/asm/elf.h
arch/arm64/include/asm/fpsimd.h
arch/arm64/include/asm/io.h
arch/arm64/include/asm/linkage.h [new file with mode: 0644]
arch/arm64/include/asm/pgtable-hwdef.h
arch/arm64/include/asm/pgtable.h
arch/arm64/include/asm/processor.h
arch/arm64/include/asm/unistd.h
arch/arm64/include/asm/unistd32.h
arch/arm64/include/uapi/asm/ptrace.h
arch/arm64/kernel/perf_event.c
arch/arm64/kernel/process.c
arch/arm64/kernel/ptrace.c
arch/arm64/kernel/setup.c
arch/arm64/kernel/smp.c
arch/arm64/kernel/vdso.c
arch/arm64/mm/init.c
arch/c6x/Makefile
arch/c6x/boot/Makefile
arch/c6x/boot/dts/Makefile [new file with mode: 0644]
arch/c6x/boot/dts/linked_dtb.S [new file with mode: 0644]
arch/c6x/boot/linked_dtb.S [deleted file]
arch/c6x/include/asm/setup.h [new file with mode: 0644]
arch/c6x/include/uapi/asm/Kbuild
arch/c6x/include/uapi/asm/kvm_para.h [deleted file]
arch/c6x/include/uapi/asm/setup.h
arch/c6x/kernel/entry.S
arch/frv/Kconfig
arch/frv/boot/Makefile
arch/frv/include/asm/unistd.h
arch/frv/kernel/entry.S
arch/frv/kernel/process.c
arch/frv/kernel/setup.c
arch/frv/mb93090-mb00/pci-dma-nommu.c
arch/h8300/include/asm/cache.h
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/kvm_para.h [deleted file]
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/xtensa/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/device.h
arch/ia64/include/asm/kvm_para.h [deleted file]
arch/ia64/include/uapi/asm/Kbuild
arch/ia64/include/uapi/asm/kvm_para.h [deleted file]
arch/ia64/kernel/acpi.c
arch/ia64/mm/init.c
arch/m68k/include/asm/Kbuild
arch/m68k/include/asm/ptrace.h
arch/m68k/include/asm/setup.h
arch/m68k/include/asm/signal.h
arch/m68k/include/asm/termios.h
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/auxvec.h [moved from arch/m68k/include/asm/auxvec.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/msgbuf.h [moved from arch/m68k/include/asm/msgbuf.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/sembuf.h [moved from arch/m68k/include/asm/sembuf.h with 100% similarity]
arch/m68k/include/uapi/asm/setup.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/shmbuf.h [moved from arch/m68k/include/asm/shmbuf.h with 100% similarity]
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/socket.h [moved from arch/m68k/include/asm/socket.h with 100% similarity]
arch/m68k/include/uapi/asm/sockios.h [moved from arch/m68k/include/asm/sockios.h with 100% similarity]
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/termbits.h [moved from arch/m68k/include/asm/termbits.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/microblaze/Makefile
arch/microblaze/boot/Makefile
arch/microblaze/boot/dts/Makefile [new file with mode: 0644]
arch/microblaze/boot/dts/linked_dtb.S [new file with mode: 0644]
arch/microblaze/boot/linked_dtb.S [deleted file]
arch/microblaze/kernel/signal.c
arch/mips/cavium-octeon/Makefile
arch/mips/cavium-octeon/executive/cvmx-l2c.c
arch/mips/fw/arc/misc.c
arch/mips/include/asm/Kbuild
arch/mips/include/asm/bitops.h
arch/mips/include/asm/compat.h
arch/mips/include/asm/delay.h
arch/mips/include/asm/hugetlb.h
arch/mips/include/asm/io.h
arch/mips/include/asm/irqflags.h
arch/mips/include/asm/pgtable-64.h
arch/mips/include/asm/thread_info.h
arch/mips/jz4740/serial.h
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/entry.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/setup.c
arch/mips/kernel/smp-cmp.c
arch/mips/lantiq/dts/Makefile
arch/mips/lib/Makefile
arch/mips/lib/bitops.c [new file with mode: 0644]
arch/mips/lib/delay.c
arch/mips/lib/dump_tlb.c
arch/mips/lib/mips-atomic.c [new file with mode: 0644]
arch/mips/mm/tlb-r4k.c
arch/mips/mm/tlbex.c
arch/mips/mti-malta/malta-platform.c
arch/mips/netlogic/dts/Makefile
arch/mn10300/include/uapi/asm/setup.h
arch/openrisc/Makefile
arch/openrisc/boot/dts/Makefile [moved from arch/openrisc/boot/Makefile with 75% similarity]
arch/openrisc/kernel/signal.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/parisc/kernel/signal32.c
arch/parisc/kernel/sys_parisc.c
arch/parisc/kernel/syscall_table.S
arch/powerpc/boot/dts/mpc5200b.dtsi
arch/powerpc/boot/dts/o2d.dtsi
arch/powerpc/boot/dts/pcm030.dts
arch/powerpc/include/asm/kvm_book3s_32.h
arch/powerpc/include/asm/processor.h
arch/powerpc/kernel/sysfs.c
arch/powerpc/kvm/book3s_32_mmu_host.c
arch/powerpc/perf/core-book3s.c
arch/powerpc/platforms/52xx/mpc52xx_pic.c
arch/powerpc/platforms/powermac/pfunc_core.c
arch/powerpc/platforms/pseries/eeh_pe.c
arch/powerpc/platforms/pseries/msi.c
arch/powerpc/platforms/pseries/processor_idle.c
arch/powerpc/platforms/pseries/reconfig.c
arch/powerpc/sysdev/fsl_pci.c
arch/powerpc/sysdev/scom.c
arch/s390/Kconfig
arch/s390/boot/compressed/vmlinux.lds.S
arch/s390/include/asm/cio.h
arch/s390/include/asm/compat.h
arch/s390/include/asm/perf_event.h
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/topology.h
arch/s390/include/uapi/asm/chpid.h
arch/s390/include/uapi/asm/kvm_para.h
arch/s390/include/uapi/asm/ptrace.h
arch/s390/kernel/cache.c
arch/s390/kernel/compat_signal.c
arch/s390/kernel/compat_wrapper.S
arch/s390/kernel/head_kdump.S
arch/s390/kernel/perf_cpum_cf.c
arch/s390/kernel/sclp.S
arch/s390/kernel/signal.c
arch/s390/kernel/topology.c
arch/s390/kernel/vmlinux.lds.S
arch/s390/lib/uaccess_pt.c
arch/s390/mm/gup.c
arch/score/kernel/signal.c
arch/sh/include/asm/Kbuild
arch/sh/include/asm/hw_breakpoint.h
arch/sh/include/asm/posix_types.h
arch/sh/include/asm/ptrace.h
arch/sh/include/asm/ptrace_32.h
arch/sh/include/asm/ptrace_64.h
arch/sh/include/asm/setup.h
arch/sh/include/asm/types.h
arch/sh/include/asm/unistd.h
arch/sh/include/uapi/asm/Kbuild
arch/sh/include/uapi/asm/auxvec.h [moved from arch/sh/include/asm/auxvec.h with 100% similarity]
arch/sh/include/uapi/asm/byteorder.h [moved from arch/sh/include/asm/byteorder.h with 100% similarity]
arch/sh/include/uapi/asm/cachectl.h [moved from arch/sh/include/asm/cachectl.h with 100% similarity]
arch/sh/include/uapi/asm/cpu-features.h [moved from arch/sh/include/asm/cpu-features.h with 100% similarity]
arch/sh/include/uapi/asm/hw_breakpoint.h [new file with mode: 0644]
arch/sh/include/uapi/asm/ioctls.h [moved from arch/sh/include/asm/ioctls.h with 100% similarity]
arch/sh/include/uapi/asm/posix_types.h [new file with mode: 0644]
arch/sh/include/uapi/asm/posix_types_32.h [moved from arch/sh/include/asm/posix_types_32.h with 100% similarity]
arch/sh/include/uapi/asm/posix_types_64.h [moved from arch/sh/include/asm/posix_types_64.h with 100% similarity]
arch/sh/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/sh/include/uapi/asm/ptrace_32.h [new file with mode: 0644]
arch/sh/include/uapi/asm/ptrace_64.h [new file with mode: 0644]
arch/sh/include/uapi/asm/setup.h [new file with mode: 0644]
arch/sh/include/uapi/asm/sigcontext.h [moved from arch/sh/include/asm/sigcontext.h with 100% similarity]
arch/sh/include/uapi/asm/signal.h [moved from arch/sh/include/asm/signal.h with 100% similarity]
arch/sh/include/uapi/asm/sockios.h [moved from arch/sh/include/asm/sockios.h with 100% similarity]
arch/sh/include/uapi/asm/stat.h [moved from arch/sh/include/asm/stat.h with 100% similarity]
arch/sh/include/uapi/asm/swab.h [moved from arch/sh/include/asm/swab.h with 100% similarity]
arch/sh/include/uapi/asm/types.h [new file with mode: 0644]
arch/sh/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/sh/include/uapi/asm/unistd_32.h [moved from arch/sh/include/asm/unistd_32.h with 99% similarity]
arch/sh/include/uapi/asm/unistd_64.h [moved from arch/sh/include/asm/unistd_64.h with 99% similarity]
arch/sh/kernel/signal_64.c
arch/sh/kernel/syscalls_32.S
arch/sh/kernel/syscalls_64.S
arch/sparc/Kconfig
arch/sparc/boot/piggyback.c
arch/sparc/crypto/Makefile
arch/sparc/crypto/aes_glue.c
arch/sparc/crypto/camellia_glue.c
arch/sparc/crypto/crc32c_glue.c
arch/sparc/crypto/des_glue.c
arch/sparc/crypto/md5_glue.c
arch/sparc/crypto/sha1_glue.c
arch/sparc/crypto/sha256_glue.c
arch/sparc/crypto/sha512_glue.c
arch/sparc/include/asm/atomic_64.h
arch/sparc/include/asm/backoff.h
arch/sparc/include/asm/compat.h
arch/sparc/include/asm/processor_64.h
arch/sparc/include/asm/prom.h
arch/sparc/include/asm/ptrace.h
arch/sparc/include/asm/smp_64.h
arch/sparc/include/asm/thread_info_64.h
arch/sparc/include/asm/ttable.h
arch/sparc/include/uapi/asm/sigcontext.h
arch/sparc/include/uapi/asm/unistd.h
arch/sparc/kernel/entry.h
arch/sparc/kernel/leon_kernel.c
arch/sparc/kernel/pci_impl.h
arch/sparc/kernel/perf_event.c
arch/sparc/kernel/process_64.c
arch/sparc/kernel/ptrace_64.c
arch/sparc/kernel/setup_64.c
arch/sparc/kernel/signal_64.c
arch/sparc/kernel/smp_64.c
arch/sparc/kernel/sys32.S
arch/sparc/kernel/sys_sparc_64.c
arch/sparc/kernel/syscalls.S
arch/sparc/kernel/systbls_32.S
arch/sparc/kernel/systbls_64.S
arch/sparc/kernel/unaligned_64.c
arch/sparc/kernel/visemul.c
arch/sparc/kernel/vmlinux.lds.S
arch/sparc/kernel/winfixup.S
arch/sparc/lib/atomic_64.S
arch/sparc/lib/ksyms.c
arch/sparc/math-emu/math_64.c
arch/sparc/mm/ultra.S
arch/tile/Makefile
arch/tile/include/arch/Kbuild
arch/tile/include/asm/Kbuild
arch/tile/include/uapi/asm/Kbuild
arch/tile/kernel/module.c
arch/um/kernel/exec.c
arch/unicore32/Kconfig
arch/unicore32/include/asm/Kbuild
arch/unicore32/include/asm/bug.h
arch/unicore32/include/asm/cmpxchg.h
arch/unicore32/include/asm/kvm_para.h [deleted file]
arch/unicore32/include/asm/processor.h
arch/unicore32/include/asm/ptrace.h
arch/unicore32/include/uapi/asm/Kbuild
arch/unicore32/include/uapi/asm/byteorder.h [moved from arch/unicore32/include/asm/byteorder.h with 100% similarity]
arch/unicore32/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/unicore32/include/uapi/asm/sigcontext.h [moved from arch/unicore32/include/asm/sigcontext.h with 100% similarity]
arch/unicore32/include/uapi/asm/unistd.h [moved from arch/unicore32/include/asm/unistd.h with 92% similarity]
arch/unicore32/kernel/entry.S
arch/unicore32/kernel/process.c
arch/unicore32/kernel/setup.h
arch/unicore32/kernel/sys.c
arch/unicore32/mm/fault.c
arch/x86/Makefile
arch/x86/boot/compressed/eboot.c
arch/x86/boot/header.S
arch/x86/crypto/aesni-intel_glue.c
arch/x86/include/asm/Kbuild
arch/x86/include/asm/device.h
arch/x86/include/asm/efi.h
arch/x86/include/asm/fpu-internal.h
arch/x86/include/asm/ptrace.h
arch/x86/include/asm/xen/hypercall.h
arch/x86/include/asm/xen/hypervisor.h
arch/x86/include/asm/xen/interface.h
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/acpi/sleep.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/cpu/amd.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/mcheck/mce_intel.c
arch/x86/kernel/cpu/perf_event.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/e820.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
arch/x86/kernel/head_32.S
arch/x86/kernel/kvm.c
arch/x86/kernel/microcode_amd.c
arch/x86/kernel/ptrace.c
arch/x86/kernel/reboot.c
arch/x86/kernel/setup.c
arch/x86/kernel/signal.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/uprobes.c
arch/x86/kvm/cpuid.h
arch/x86/kvm/emulate.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/mm/init.c
arch/x86/mm/init_64.c
arch/x86/mm/tlb.c
arch/x86/oprofile/nmi_int.c
arch/x86/pci/ce4100.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/xen/enlighten.c
arch/x86/xen/mmu.c
arch/xtensa/Kconfig
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/io.h
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/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/processor.h
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/syscall.h
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/kernel/xtensa_ksyms.c
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/Kconfig
block/blk-cgroup.c
block/blk-core.c
block/blk-exec.c
crypto/cryptd.c
drivers/Makefile
drivers/acpi/Kconfig
drivers/acpi/Makefile
drivers/acpi/acpi_i2c.c [new file with mode: 0644]
drivers/acpi/acpi_memhotplug.c
drivers/acpi/acpi_pad.c
drivers/acpi/acpi_platform.c [new file with mode: 0644]
drivers/acpi/acpica/Makefile
drivers/acpi/acpica/acdebug.h
drivers/acpi/acpica/acdispat.h
drivers/acpi/acpica/acevents.h
drivers/acpi/acpica/acglobal.h
drivers/acpi/acpica/aclocal.h
drivers/acpi/acpica/acmacros.h
drivers/acpi/acpica/acobject.h
drivers/acpi/acpica/acopcode.h
drivers/acpi/acpica/acparser.h
drivers/acpi/acpica/acpredef.h
drivers/acpi/acpica/acstruct.h
drivers/acpi/acpica/acutils.h
drivers/acpi/acpica/amlresrc.h
drivers/acpi/acpica/dscontrol.c
drivers/acpi/acpica/dsfield.c
drivers/acpi/acpica/dsmethod.c
drivers/acpi/acpica/dsmthdat.c
drivers/acpi/acpica/dsobject.c
drivers/acpi/acpica/dsopcode.c
drivers/acpi/acpica/dsutils.c
drivers/acpi/acpica/dswexec.c
drivers/acpi/acpica/dswload2.c
drivers/acpi/acpica/dswstate.c
drivers/acpi/acpica/evgpe.c
drivers/acpi/acpica/evgpeblk.c
drivers/acpi/acpica/evgpeutil.c
drivers/acpi/acpica/evrgnini.c
drivers/acpi/acpica/evxface.c
drivers/acpi/acpica/evxfgpe.c
drivers/acpi/acpica/exconvrt.c
drivers/acpi/acpica/excreate.c
drivers/acpi/acpica/exdebug.c
drivers/acpi/acpica/exdump.c
drivers/acpi/acpica/exfield.c
drivers/acpi/acpica/exfldio.c
drivers/acpi/acpica/exmisc.c
drivers/acpi/acpica/exmutex.c
drivers/acpi/acpica/exnames.c
drivers/acpi/acpica/exoparg1.c
drivers/acpi/acpica/exoparg2.c
drivers/acpi/acpica/exoparg3.c
drivers/acpi/acpica/exoparg6.c
drivers/acpi/acpica/exprep.c
drivers/acpi/acpica/exregion.c
drivers/acpi/acpica/exresnte.c
drivers/acpi/acpica/exresolv.c
drivers/acpi/acpica/exresop.c
drivers/acpi/acpica/exstore.c
drivers/acpi/acpica/exstoren.c
drivers/acpi/acpica/exstorob.c
drivers/acpi/acpica/exsystem.c
drivers/acpi/acpica/exutils.c
drivers/acpi/acpica/hwacpi.c
drivers/acpi/acpica/hwgpe.c
drivers/acpi/acpica/hwpci.c
drivers/acpi/acpica/hwregs.c
drivers/acpi/acpica/hwtimer.c
drivers/acpi/acpica/hwvalid.c
drivers/acpi/acpica/hwxface.c
drivers/acpi/acpica/hwxfsleep.c
drivers/acpi/acpica/nsaccess.c
drivers/acpi/acpica/nsalloc.c
drivers/acpi/acpica/nsdump.c
drivers/acpi/acpica/nsinit.c
drivers/acpi/acpica/nsload.c
drivers/acpi/acpica/nsnames.c
drivers/acpi/acpica/nsobject.c
drivers/acpi/acpica/nsparse.c
drivers/acpi/acpica/nssearch.c
drivers/acpi/acpica/nsutils.c
drivers/acpi/acpica/nswalk.c
drivers/acpi/acpica/nsxfeval.c
drivers/acpi/acpica/nsxfname.c
drivers/acpi/acpica/nsxfobj.c
drivers/acpi/acpica/psargs.c
drivers/acpi/acpica/psloop.c
drivers/acpi/acpica/psopcode.c
drivers/acpi/acpica/psparse.c
drivers/acpi/acpica/psutils.c
drivers/acpi/acpica/rscalc.c
drivers/acpi/acpica/rslist.c
drivers/acpi/acpica/tbfind.c
drivers/acpi/acpica/tbinstal.c
drivers/acpi/acpica/tbutils.c
drivers/acpi/acpica/tbxface.c
drivers/acpi/acpica/tbxfload.c
drivers/acpi/acpica/tbxfroot.c
drivers/acpi/acpica/utcache.c [new file with mode: 0644]
drivers/acpi/acpica/utclib.c [new file with mode: 0644]
drivers/acpi/acpica/utdebug.c
drivers/acpi/acpica/utids.c
drivers/acpi/acpica/utmath.c
drivers/acpi/acpica/utmisc.c
drivers/acpi/acpica/utmutex.c
drivers/acpi/acpica/utobject.c
drivers/acpi/acpica/utstate.c
drivers/acpi/acpica/uttrack.c [new file with mode: 0644]
drivers/acpi/acpica/utxface.c
drivers/acpi/acpica/utxferror.c
drivers/acpi/apei/ghes.c
drivers/acpi/battery.c
drivers/acpi/bus.c
drivers/acpi/container.c
drivers/acpi/device_pm.c [new file with mode: 0644]
drivers/acpi/dock.c
drivers/acpi/ec.c
drivers/acpi/glue.c
drivers/acpi/hed.c
drivers/acpi/internal.h
drivers/acpi/osl.c
drivers/acpi/pci_irq.c
drivers/acpi/power.c
drivers/acpi/proc.c
drivers/acpi/processor_driver.c
drivers/acpi/processor_idle.c
drivers/acpi/resource.c [new file with mode: 0644]
drivers/acpi/scan.c
drivers/acpi/sleep.c
drivers/acpi/sysfs.c
drivers/acpi/thermal.c
drivers/acpi/utils.c
drivers/acpi/video.c
drivers/acpi/video_detect.c
drivers/ata/ahci_platform.c
drivers/ata/libata-acpi.c
drivers/ata/libata-core.c
drivers/ata/libata-scsi.c
drivers/ata/pata_arasan_cf.c
drivers/ata/sata_highbank.c
drivers/ata/sata_svw.c
drivers/atm/ambassador.c
drivers/base/Kconfig
drivers/base/core.c
drivers/base/dma-coherent.c
drivers/base/dma-contiguous.c
drivers/base/firmware_class.c
drivers/base/platform.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/bcma/main.c
drivers/block/Kconfig
drivers/block/aoe/aoecmd.c
drivers/block/cciss.c
drivers/block/floppy.c
drivers/block/loop.c
drivers/block/mtip32xx/mtip32xx.c
drivers/block/mtip32xx/mtip32xx.h
drivers/block/xen-blkback/common.h
drivers/block/xen-blkback/xenbus.c
drivers/bluetooth/ath3k.c
drivers/bluetooth/btusb.c
drivers/bus/omap-ocp2scp.c
drivers/char/Makefile
drivers/char/agp/intel-gtt.c
drivers/char/hw_random/Kconfig
drivers/char/hw_random/ixp4xx-rng.c
drivers/char/ipmi/ipmi_msghandler.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/raw.c
drivers/char/sonypi.c
drivers/clk/Kconfig
drivers/clk/Makefile
drivers/clk/clk-bcm2835.c
drivers/clk/clk-fixed-rate.c
drivers/clk/clk-prima2.c
drivers/clk/clk-twl6040.c [new file with mode: 0644]
drivers/clk/clk-vt8500.c
drivers/clk/clk-wm831x.c
drivers/clk/clk.c
drivers/clk/mxs/clk-imx23.c
drivers/clk/mxs/clk-imx28.c
drivers/clk/spear/clk-aux-synth.c
drivers/clk/spear/clk-vco-pll.c
drivers/clk/spear/clk.c
drivers/clk/spear/spear1310_clock.c
drivers/clk/spear/spear1340_clock.c
drivers/clk/spear/spear3xx_clock.c
drivers/clk/spear/spear6xx_clock.c
drivers/clk/ux500/Makefile
drivers/clk/ux500/abx500-clk.c [new file with mode: 0644]
drivers/clk/ux500/clk-prcmu.c
drivers/clk/ux500/clk.h
drivers/clk/ux500/u8500_clk.c
drivers/clk/versatile/Makefile
drivers/clk/versatile/clk-icst.c
drivers/clk/versatile/clk-icst.h
drivers/clk/versatile/clk-impd1.c [new file with mode: 0644]
drivers/clk/versatile/clk-integrator.c
drivers/clk/versatile/clk-realview.c
drivers/clk/versatile/clk-vexpress-osc.c [new file with mode: 0644]
drivers/clk/versatile/clk-vexpress.c [new file with mode: 0644]
drivers/cpufreq/Kconfig.arm
drivers/cpufreq/Makefile
drivers/cpufreq/cpufreq-cpu0.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_conservative.c
drivers/cpufreq/cpufreq_governor.c [new file with mode: 0644]
drivers/cpufreq/cpufreq_governor.h [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/db8500-cpufreq.c
drivers/cpufreq/exynos-cpufreq.c
drivers/cpufreq/freq_table.c
drivers/cpufreq/longhaul.c
drivers/cpufreq/powernow-k8.c
drivers/cpufreq/spear-cpufreq.c [new file with mode: 0644]
drivers/cpuidle/Kconfig
drivers/cpuidle/cpuidle.c
drivers/cpuidle/cpuidle.h
drivers/cpuidle/driver.c
drivers/cpuidle/governors/menu.c
drivers/cpuidle/sysfs.c
drivers/crypto/Kconfig
drivers/crypto/ixp4xx_crypto.c
drivers/devfreq/Kconfig
drivers/devfreq/devfreq.c
drivers/devfreq/exynos4_bus.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/dw_dmac_regs.h
drivers/dma/imx-dma.c
drivers/dma/sirf-dma.c
drivers/edac/Kconfig
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/edac_pci_sysfs.c
drivers/edac/edac_stub.c
drivers/edac/highbank_mc_edac.c
drivers/edac/i7300_edac.c
drivers/edac/i7core_edac.c
drivers/edac/i82975x_edac.c
drivers/edac/mce_amd.c
drivers/edac/mce_amd.h
drivers/edac/mce_amd_inj.c
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/firewire/sbp2.c
drivers/firmware/memmap.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-74x164.c
drivers/gpio/gpio-mcp23s08.c
drivers/gpio/gpio-mvebu.c
drivers/gpio/gpio-omap.c
drivers/gpio/gpio-timberdale.c
drivers/gpio/gpiolib-acpi.c [new file with mode: 0644]
drivers/gpio/gpiolib-of.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/drm_fb_cma_helper.c
drivers/gpu/drm/drm_fops.c
drivers/gpu/drm/drm_info.c
drivers/gpu/drm/drm_platform.c
drivers/gpu/drm/exynos/Kconfig
drivers/gpu/drm/exynos/exynos_drm_connector.c
drivers/gpu/drm/exynos/exynos_drm_encoder.c
drivers/gpu/drm/exynos/exynos_drm_fbdev.c
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/exynos/exynos_drm_plane.c
drivers/gpu/drm/exynos/exynos_mixer.c
drivers/gpu/drm/i915/dvo_ch7xxx.c
drivers/gpu/drm/i915/i915_dma.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/i915_reg.h
drivers/gpu/drm/i915/intel_bios.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_overlay.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_sdvo_regs.h
drivers/gpu/drm/nouveau/core/core/gpuobj.c
drivers/gpu/drm/nouveau/core/core/mm.c
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c
drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
drivers/gpu/drm/nouveau/core/engine/graph/nv40.h
drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c
drivers/gpu/drm/nouveau/core/include/core/mm.h
drivers/gpu/drm/nouveau/core/include/core/object.h
drivers/gpu/drm/nouveau/core/include/subdev/clock.h
drivers/gpu/drm/nouveau/core/subdev/bios/base.c
drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c
drivers/gpu/drm/nouveau/core/subdev/bios/pll.c
drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c
drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c
drivers/gpu/drm/nouveau/nouveau_abi16.c
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nouveau_drm.h
drivers/gpu/drm/nouveau/nouveau_irq.c
drivers/gpu/drm/nouveau/nouveau_pm.c
drivers/gpu/drm/nouveau/nv04_dac.c
drivers/gpu/drm/nouveau/nv04_dfp.c
drivers/gpu/drm/nouveau/nv04_tv.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/atombios_encoders.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_cs.c
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/nid.h
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_acpi.c
drivers/gpu/drm/radeon/radeon_agp.c
drivers/gpu/drm/radeon/radeon_atpx_handler.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_gart.c
drivers/gpu/drm/radeon/radeon_gem.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/radeon_legacy_crtc.c
drivers/gpu/drm/radeon/radeon_legacy_encoders.c
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/radeon_ring.c
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/radeon/sid.h
drivers/gpu/drm/shmobile/shmob_drm_drv.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/ttm/ttm_page_alloc.c
drivers/gpu/drm/ttm/ttm_tt.c
drivers/gpu/drm/udl/udl_drv.h
drivers/gpu/drm/udl/udl_fb.c
drivers/gpu/drm/udl/udl_transfer.c
drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
drivers/hid/hid-apple.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-microsoft.c
drivers/hid/hid-multitouch.c
drivers/hid/hidraw.c
drivers/hv/channel.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/fam15h_power.c
drivers/hwmon/gpio-fan.c
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-at91.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-mxs.c
drivers/i2c/busses/i2c-nomadik.c
drivers/i2c/busses/i2c-ocores.c
drivers/i2c/busses/i2c-omap.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/busses/i2c-tegra.c
drivers/i2c/i2c-core.c
drivers/i2c/i2c-stub.c [moved from drivers/i2c/busses/i2c-stub.c with 75% similarity]
drivers/i2c/muxes/i2c-mux-pinctrl.c
drivers/idle/intel_idle.c
drivers/iio/Kconfig
drivers/iio/Makefile
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/input-mt.c
drivers/input/joydev.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/pxa27x_keypad.c
drivers/input/matrix-keymap.c
drivers/input/misc/xen-kbdfront.c
drivers/input/mouse/bcm5974.c
drivers/input/mousedev.c
drivers/input/tablet/wacom_sys.c
drivers/input/tablet/wacom_wac.c
drivers/input/tablet/wacom_wac.h
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/egalax_ts.c
drivers/input/touchscreen/tsc40.c
drivers/iommu/amd_iommu_init.c
drivers/iommu/intel-iommu.c
drivers/iommu/tegra-smmu.c
drivers/irqchip/irq-bcm2835.c
drivers/isdn/Kconfig
drivers/isdn/gigaset/bas-gigaset.c
drivers/isdn/i4l/Kconfig
drivers/isdn/i4l/isdn_common.c
drivers/leds/ledtrig-cpu.c
drivers/md/dm.c
drivers/md/faulty.c
drivers/md/md.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/media/Kconfig
drivers/media/dvb-frontends/stv0900_core.c
drivers/media/i2c/adv7604.c
drivers/media/i2c/soc_camera/mt9v022.c
drivers/media/platform/exynos-gsc/gsc-core.c
drivers/media/platform/exynos-gsc/gsc-m2m.c
drivers/media/platform/exynos-gsc/gsc-regs.h
drivers/media/platform/omap3isp/ispccdc.c
drivers/media/platform/omap3isp/ispstat.c
drivers/media/platform/omap3isp/ispstat.h
drivers/media/platform/omap3isp/ispvideo.c
drivers/media/platform/s5p-fimc/Kconfig
drivers/media/platform/s5p-fimc/fimc-capture.c
drivers/media/platform/s5p-fimc/fimc-lite.c
drivers/media/platform/s5p-fimc/fimc-m2m.c
drivers/media/platform/s5p-fimc/fimc-mdevice.c
drivers/media/platform/s5p-mfc/s5p_mfc.c
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
drivers/media/platform/sh_vou.c
drivers/media/platform/soc_camera/mx1_camera.c
drivers/media/platform/soc_camera/mx2_camera.c
drivers/media/platform/soc_camera/mx3_camera.c
drivers/media/platform/soc_camera/omap1_camera.c
drivers/media/platform/soc_camera/pxa_camera.c
drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c
drivers/media/usb/dvb-usb-v2/rtl28xxu.c
drivers/mfd/arizona-core.c
drivers/mfd/arizona-irq.c
drivers/mfd/db8500-prcmu.c
drivers/mfd/twl-core.c
drivers/mfd/twl4030-irq.c
drivers/mfd/wm5102-tables.c
drivers/mmc/card/block.c
drivers/mmc/card/queue.c
drivers/mmc/core/bus.c
drivers/mmc/core/core.c
drivers/mmc/core/debugfs.c
drivers/mmc/core/mmc.c
drivers/mmc/core/mmc_ops.c
drivers/mmc/core/sdio_bus.c
drivers/mmc/core/sdio_io.c
drivers/mmc/core/sdio_ops.c
drivers/mmc/core/slot-gpio.c
drivers/mmc/host/Kconfig
drivers/mmc/host/Makefile
drivers/mmc/host/at91_mci.c [deleted file]
drivers/mmc/host/at91_mci.h [deleted file]
drivers/mmc/host/dw_mmc-exynos.c
drivers/mmc/host/dw_mmc-pci.c
drivers/mmc/host/dw_mmc-pltfm.c
drivers/mmc/host/dw_mmc-pltfm.h
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/mxcmmc.c
drivers/mmc/host/mxs-mmc.c
drivers/mmc/host/omap_hsmmc.c
drivers/mmc/host/sdhci-acpi.c [new file with mode: 0644]
drivers/mmc/host/sdhci-dove.c
drivers/mmc/host/sdhci-esdhc-imx.c
drivers/mmc/host/sdhci-of-esdhc.c
drivers/mmc/host/sdhci-pci.c
drivers/mmc/host/sdhci-pltfm.c
drivers/mmc/host/sdhci-pxav3.c
drivers/mmc/host/sdhci-s3c.c
drivers/mmc/host/sdhci-spear.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h
drivers/mmc/host/sh_mmcif.c
drivers/mmc/host/sh_mobile_sdhi.c
drivers/mmc/host/vub300.c
drivers/mmc/host/wmt-sdmmc.c [new file with mode: 0644]
drivers/mtd/devices/slram.c
drivers/mtd/mtdcore.c
drivers/mtd/nand/atmel_nand.c
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/sh_flctl.c
drivers/mtd/ofpart.c
drivers/mtd/onenand/onenand_base.c
drivers/mtd/ubi/wl.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_sysfs.c
drivers/net/can/flexcan.c
drivers/net/can/sja1000/peak_pci.c
drivers/net/can/usb/peak_usb/pcan_usb.c
drivers/net/can/usb/peak_usb/pcan_usb_pro.c
drivers/net/ethernet/8390/ne.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
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/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/freescale/gianfar_ptp.c
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
drivers/net/ethernet/jme.c
drivers/net/ethernet/marvell/skge.c
drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
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/micrel/ksz884x.c
drivers/net/ethernet/nxp/lpc_eth.c
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
drivers/net/ethernet/qlogic/qla3xxx.c
drivers/net/ethernet/realtek/8139cp.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/sis/sis900.c
drivers/net/ethernet/smsc/smsc911x.c
drivers/net/ethernet/ti/Kconfig
drivers/net/ethernet/tile/tilegx.c
drivers/net/ethernet/xilinx/xilinx_axienet_main.c
drivers/net/ethernet/xscale/ixp4xx_eth.c
drivers/net/irda/sir_dev.c
drivers/net/phy/Kconfig
drivers/net/phy/Makefile
drivers/net/phy/at803x.c [new file with mode: 0644]
drivers/net/phy/mdio-gpio.c
drivers/net/team/team.c
drivers/net/team/team_mode_broadcast.c
drivers/net/usb/cdc_eem.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/ipheth.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/smsc95xx.c
drivers/net/usb/usbnet.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vxlan.c
drivers/net/wan/ixp4xx_hss.c
drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
drivers/net/wireless/ath/ath9k/hif_usb.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/b43/main.c
drivers/net/wireless/b43legacy/pio.c
drivers/net/wireless/brcm80211/brcmfmac/usb.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
drivers/net/wireless/ipw2x00/ipw2200.c
drivers/net/wireless/iwlwifi/dvm/devices.c
drivers/net/wireless/iwlwifi/dvm/mac80211.c
drivers/net/wireless/iwlwifi/dvm/main.c
drivers/net/wireless/iwlwifi/dvm/rxon.c
drivers/net/wireless/iwlwifi/pcie/rx.c
drivers/net/wireless/iwlwifi/pcie/tx.c
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/cmdevt.c
drivers/net/wireless/mwifiex/scan.c
drivers/net/wireless/mwifiex/sdio.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/rtl8192cu/sw.c
drivers/net/wireless/rtlwifi/usb.c
drivers/net/xen-netfront.c
drivers/nfc/pn533.c
drivers/of/address.c
drivers/of/base.c
drivers/of/fdt.c
drivers/of/irq.c
drivers/of/of_i2c.c
drivers/of/of_mdio.c
drivers/of/pdt.c
drivers/of/platform.c
drivers/pci/bus.c
drivers/pci/pci-acpi.c
drivers/pci/pci-driver.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/aer/aerdrv_core.c
drivers/pci/pcie/portdrv_core.c
drivers/pci/proc.c
drivers/pcmcia/pxa2xx_sharpsl.c
drivers/pinctrl/Kconfig
drivers/pinctrl/Makefile
drivers/pinctrl/core.c
drivers/pinctrl/core.h
drivers/pinctrl/devicetree.c
drivers/pinctrl/mvebu/Kconfig [new file with mode: 0644]
drivers/pinctrl/mvebu/Makefile [new file with mode: 0644]
drivers/pinctrl/mvebu/pinctrl-armada-370.c [moved from drivers/pinctrl/pinctrl-armada-370.c with 100% similarity]
drivers/pinctrl/mvebu/pinctrl-armada-xp.c [moved from drivers/pinctrl/pinctrl-armada-xp.c with 100% similarity]
drivers/pinctrl/mvebu/pinctrl-dove.c [moved from drivers/pinctrl/pinctrl-dove.c with 100% similarity]
drivers/pinctrl/mvebu/pinctrl-kirkwood.c [moved from drivers/pinctrl/pinctrl-kirkwood.c with 100% similarity]
drivers/pinctrl/mvebu/pinctrl-mvebu.c [moved from drivers/pinctrl/pinctrl-mvebu.c with 99% similarity]
drivers/pinctrl/mvebu/pinctrl-mvebu.h [moved from drivers/pinctrl/pinctrl-mvebu.h with 100% similarity]
drivers/pinctrl/pinconf-generic.c
drivers/pinctrl/pinconf.c
drivers/pinctrl/pinctrl-at91.c [new file with mode: 0644]
drivers/pinctrl/pinctrl-bcm2835.c
drivers/pinctrl/pinctrl-coh901.c
drivers/pinctrl/pinctrl-exynos.c
drivers/pinctrl/pinctrl-falcon.c
drivers/pinctrl/pinctrl-imx.c
drivers/pinctrl/pinctrl-lantiq.c
drivers/pinctrl/pinctrl-mxs.c
drivers/pinctrl/pinctrl-nomadik-db8500.c
drivers/pinctrl/pinctrl-nomadik-db8540.c
drivers/pinctrl/pinctrl-nomadik.c
drivers/pinctrl/pinctrl-nomadik.h
drivers/pinctrl/pinctrl-pxa3xx.c
drivers/pinctrl/pinctrl-pxa3xx.h
drivers/pinctrl/pinctrl-samsung.c
drivers/pinctrl/pinctrl-single.c
drivers/pinctrl/pinctrl-sirf.c
drivers/pinctrl/pinctrl-tegra.c
drivers/pinctrl/pinctrl-tegra30.c
drivers/pinctrl/pinctrl-u300.c
drivers/pinctrl/pinctrl-xway.c
drivers/pinctrl/pinmux.c
drivers/pinctrl/spear/Kconfig
drivers/pinctrl/spear/Makefile
drivers/pinctrl/spear/pinctrl-plgpio.c [new file with mode: 0644]
drivers/pinctrl/spear/pinctrl-spear.c
drivers/pinctrl/spear/pinctrl-spear.h
drivers/pinctrl/spear/pinctrl-spear1310.c
drivers/pinctrl/spear/pinctrl-spear1340.c
drivers/pinctrl/spear/pinctrl-spear300.c
drivers/pinctrl/spear/pinctrl-spear310.c
drivers/pinctrl/spear/pinctrl-spear320.c
drivers/pinctrl/spear/pinctrl-spear3xx.c
drivers/pinctrl/spear/pinctrl-spear3xx.h
drivers/pnp/base.h
drivers/pnp/pnpacpi/core.c
drivers/pnp/pnpacpi/rsparser.c
drivers/pnp/resource.c
drivers/rapidio/rio.c
drivers/regulator/core.c
drivers/remoteproc/remoteproc_virtio.c
drivers/rtc/rtc-imxdi.c
drivers/rtc/rtc-tps65910.c
drivers/s390/char/con3215.c
drivers/s390/cio/css.c
drivers/s390/cio/css.h
drivers/s390/cio/device.c
drivers/s390/cio/idset.c
drivers/s390/cio/idset.h
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l3_main.c
drivers/s390/net/smsgiucv.c
drivers/scsi/arm/fas216.c
drivers/scsi/arm/oak.c
drivers/scsi/isci/request.c
drivers/scsi/megaraid/megaraid_sas.h
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/qla2xxx/qla_mid.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/qla2xxx/qla_target.h
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/scsi/qla2xxx/tcm_qla2xxx.h
drivers/scsi/qlogicpti.c
drivers/scsi/scsi.c
drivers/scsi/scsi_lib.c
drivers/scsi/sd.c
drivers/scsi/sd.h
drivers/sh/intc/access.c
drivers/sh/intc/chip.c
drivers/spi/spi-mxs.c
drivers/spi/spi-pl022.c
drivers/spi/spi-rspi.c
drivers/spi/spi-s3c64xx.c
drivers/spi/spi.c
drivers/staging/android/android_alarm.h
drivers/staging/android/binder.c
drivers/staging/comedi/drivers/8255_pci.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/das08.c
drivers/staging/comedi/drivers/ni_daq_700.c
drivers/staging/comedi/drivers/ni_labpc.c
drivers/staging/dgrp/dgrp_mon_ops.c
drivers/staging/dgrp/dgrp_specproc.c
drivers/staging/dgrp/dgrp_tty.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/adis16220_core.c
drivers/staging/iio/accel/adis16240_core.c
drivers/staging/iio/gyro/adis16260_core.c
drivers/staging/iio/imu/adis16400.h
drivers/staging/iio/imu/adis16400_core.c
drivers/staging/ipack/bridges/tpci200.c
drivers/staging/omapdrm/omap_gem.c
drivers/staging/ramster/Kconfig
drivers/staging/tidspbridge/core/tiomap3430.c
drivers/staging/tidspbridge/hw/hw_mmu.c
drivers/staging/tidspbridge/hw/hw_mmu.h
drivers/staging/tidspbridge/include/dspbridge/cfgdefs.h
drivers/staging/tidspbridge/include/dspbridge/host_os.h
drivers/staging/tidspbridge/rmgr/drv.c
drivers/staging/tidspbridge/rmgr/node.c
drivers/staging/zram/zram_drv.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_core.h
drivers/target/iscsi/iscsi_target_login.c
drivers/target/iscsi/iscsi_target_util.c
drivers/target/iscsi/iscsi_target_util.h
drivers/target/target_core_configfs.c
drivers/target/target_core_device.c
drivers/target/target_core_sbc.c
drivers/target/target_core_spc.c
drivers/target/target_core_tmr.c
drivers/target/target_core_transport.c
drivers/thermal/Kconfig
drivers/thermal/exynos_thermal.c
drivers/thermal/rcar_thermal.c
drivers/tty/hvc/hvc_console.c
drivers/tty/serial/8250/8250_hp300.c
drivers/tty/serial/Kconfig
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/max310x.c
drivers/tty/serial/omap-serial.c
drivers/tty/serial/sccnxp.c
drivers/tty/serial/sh-sci.c
drivers/tty/sysrq.c
drivers/tty/vt/vt.c
drivers/usb/class/cdc-acm.c
drivers/usb/core/devio.c
drivers/usb/core/driver.c
drivers/usb/core/hcd.c
drivers/usb/core/hub.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/gadget.c
drivers/usb/early/ehci-dbgp.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/lpc32xx_udc.c
drivers/usb/gadget/net2272.c
drivers/usb/gadget/u_ether.c
drivers/usb/host/ehci-fsl.c
drivers/usb/host/ehci-ls1x.c
drivers/usb/host/ehci-orion.c
drivers/usb/host/ehci-vt8500.c
drivers/usb/host/ohci-xls.c
drivers/usb/host/pci-quirks.c
drivers/usb/host/uhci-platform.c
drivers/usb/host/xhci-dbg.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/misc/ezusb.c
drivers/usb/musb/am35x.c
drivers/usb/musb/musb_dsps.c
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/ux500.c
drivers/usb/otg/Kconfig
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/ch341.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/cyberjack.c
drivers/usb/serial/cypress_m8.c
drivers/usb/serial/digi_acceleport.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/ipw.c
drivers/usb/serial/iuu_phoenix.c
drivers/usb/serial/keyspan.c
drivers/usb/serial/keyspan.h
drivers/usb/serial/keyspan_pda.c
drivers/usb/serial/kl5kusb105.c
drivers/usb/serial/kobil_sct.c
drivers/usb/serial/mct_u232.c
drivers/usb/serial/metro-usb.c
drivers/usb/serial/mos7720.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/omninet.c
drivers/usb/serial/opticon.c
drivers/usb/serial/option.c
drivers/usb/serial/oti6858.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/qcserial.c
drivers/usb/serial/quatech2.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/serial/usb-wwan.h
drivers/usb/serial/usb_wwan.c
drivers/usb/serial/whiteheat.c
drivers/usb/storage/scsiglue.c
drivers/usb/storage/unusual_devs.h
drivers/vhost/net.c
drivers/vhost/vhost.c
drivers/video/backlight/Kconfig
drivers/video/backlight/lm3639_bl.c
drivers/video/omap2/dss/dsi.c
drivers/video/omap2/dss/dss.c
drivers/video/omap2/dss/hdmi.c
drivers/video/omap2/omapfb/omapfb-ioctl.c
drivers/video/xen-fbfront.c
drivers/virtio/virtio.c
drivers/xen/Kconfig
drivers/xen/Makefile
drivers/xen/balloon.c
drivers/xen/dbgp.c
drivers/xen/events.c
drivers/xen/fallback.c [new file with mode: 0644]
drivers/xen/gntdev.c
drivers/xen/grant-table.c
drivers/xen/privcmd.c
drivers/xen/sys-hypervisor.c
drivers/xen/xen-pciback/vpci.c
drivers/xen/xenbus/xenbus_dev_frontend.c
drivers/xen/xenbus/xenbus_xs.c
fs/bio.c
fs/block_dev.c
fs/btrfs/backref.c
fs/btrfs/backref.h
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/extent_io.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/qgroup.c
fs/btrfs/send.c
fs/btrfs/transaction.c
fs/btrfs/volumes.c
fs/buffer.c
fs/ceph/export.c
fs/char_dev.c
fs/cifs/cifsacl.c
fs/cifs/dir.c
fs/cifs/file.c
fs/cifs/readdir.c
fs/cifs/smb1ops.c
fs/compat_ioctl.c
fs/coredump.c
fs/direct-io.c
fs/eventpoll.c
fs/exec.c
fs/ext2/super.c
fs/ext3/balloc.c
fs/ext3/namei.c
fs/ext3/namei.h
fs/ext3/super.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/file.c
fs/fs-writeback.c
fs/gfs2/file.c
fs/gfs2/lops.c
fs/gfs2/quota.c
fs/gfs2/rgrp.c
fs/gfs2/super.c
fs/gfs2/trans.c
fs/inode.c
fs/internal.h
fs/jbd/transaction.c
fs/jffs2/file.c
fs/jfs/jfs_discard.c
fs/lockd/clntxdr.c
fs/lockd/mon.c
fs/lockd/svcproc.c
fs/namei.c
fs/nfs/callback.c
fs/nfs/dir.c
fs/nfs/dns_resolve.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/mount_clnt.c
fs/nfs/namespace.c
fs/nfs/nfs4filelayout.c
fs/nfs/nfs4filelayout.h
fs/nfs/nfs4filelayoutdev.c
fs/nfs/nfs4getroot.c
fs/nfs/nfs4namespace.c
fs/nfs/nfs4proc.c
fs/nfs/objlayout/objio_osd.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h
fs/nfs/super.c
fs/nfs/unlink.c
fs/notify/fanotify/fanotify.c
fs/notify/fanotify/fanotify_user.c
fs/proc/base.c
fs/proc/internal.h
fs/proc/stat.c
fs/proc/task_mmu.c
fs/pstore/platform.c
fs/quota/dquot.c
fs/reiserfs/inode.c
fs/reiserfs/stree.c
fs/reiserfs/super.c
fs/sysfs/dir.c
fs/ubifs/find.c
fs/ubifs/lprops.c
fs/ubifs/ubifs.h
fs/xattr.c
fs/xfs/xfs_alloc.c
fs/xfs/xfs_alloc.h
fs/xfs/xfs_alloc_btree.c
fs/xfs/xfs_aops.c
fs/xfs/xfs_attr_leaf.c
fs/xfs/xfs_bmap.c
fs/xfs/xfs_bmap.h
fs/xfs/xfs_buf.c
fs/xfs/xfs_buf_item.c
fs/xfs/xfs_fsops.c
fs/xfs/xfs_ialloc.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_ioctl.c
fs/xfs/xfs_iomap.c
fs/xfs/xfs_log.c
fs/xfs/xfs_log_recover.c
include/Kbuild
include/acpi/acconfig.h
include/acpi/acexcep.h
include/acpi/acnames.h
include/acpi/acpi_bus.h
include/acpi/acpiosxf.h
include/acpi/acpixf.h
include/acpi/actbl3.h
include/acpi/actypes.h
include/asm-generic/Kbuild [deleted file]
include/asm-generic/gpio.h
include/drm/Kbuild [deleted file]
include/drm/drm_pciids.h
include/linux/Kbuild
include/linux/acpi.h
include/linux/acpi_gpio.h [new file with mode: 0644]
include/linux/bug.h
include/linux/byteorder/Kbuild [deleted file]
include/linux/caif/Kbuild [deleted file]
include/linux/can/Kbuild [deleted file]
include/linux/clk-provider.h
include/linux/coredump.h
include/linux/cpufreq.h
include/linux/cpuidle.h
include/linux/devfreq.h
include/linux/device.h
include/linux/dma-contiguous.h
include/linux/dvb/Kbuild
include/linux/dvb/dmx.h
include/linux/dvb/video.h
include/linux/dynamic_debug.h
include/linux/edac.h
include/linux/elf-fdpic.h [new file with mode: 0644]
include/linux/extcon.h
include/linux/freezer.h
include/linux/fs.h
include/linux/gfp.h
include/linux/gpio.h
include/linux/hashtable.h [new file with mode: 0644]
include/linux/hsi/Kbuild
include/linux/hw_breakpoint.h
include/linux/i2c-omap.h
include/linux/i2c.h
include/linux/iio/iio.h
include/linux/isdn/Kbuild [deleted file]
include/linux/kernel.h
include/linux/kvm_host.h
include/linux/memblock.h
include/linux/mempolicy.h
include/linux/mfd/db8500-prcmu.h
include/linux/mfd/dbx500-prcmu.h
include/linux/mfd/max77693.h
include/linux/mm.h
include/linux/mmc/Kbuild [deleted file]
include/linux/mmc/card.h
include/linux/mmc/core.h
include/linux/mmc/dw_mmc.h
include/linux/mmc/host.h
include/linux/mmc/mmc.h
include/linux/mmc/mxs-mmc.h [deleted file]
include/linux/mmc/sdhci.h
include/linux/mmzone.h
include/linux/netdevice.h
include/linux/netfilter/Kbuild [deleted file]
include/linux/netfilter/ipset/Kbuild [deleted file]
include/linux/netfilter_arp/Kbuild [deleted file]
include/linux/netfilter_bridge/Kbuild [deleted file]
include/linux/netfilter_ipv4/Kbuild [deleted file]
include/linux/netfilter_ipv6/Kbuild [deleted file]
include/linux/nfsd/Kbuild [deleted file]
include/linux/of.h
include/linux/of_address.h
include/linux/of_irq.h
include/linux/percpu-rwsem.h
include/linux/perf_event.h
include/linux/pid_namespace.h
include/linux/pinctrl/pinconf-generic.h
include/linux/pinctrl/pinctrl.h
include/linux/platform_data/ads7828.h [new file with mode: 0644]
include/linux/platform_data/clk-integrator.h
include/linux/platform_data/omap_ocp2scp.h [new file with mode: 0644]
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/pxa_sdhci.h
include/linux/platform_device.h
include/linux/pm.h
include/linux/pm_qos.h
include/linux/ptp_clock_kernel.h
include/linux/raid/Kbuild
include/linux/raid/md_u.h
include/linux/ratelimit.h
include/linux/rbtree_augmented.h
include/linux/rio.h
include/linux/spi/Kbuild [deleted file]
include/linux/spi/ads7846.h
include/linux/spi/tsc2005.h
include/linux/sunrpc/Kbuild [deleted file]
include/linux/tc_act/Kbuild [deleted file]
include/linux/tc_ematch/Kbuild [deleted file]
include/linux/tcp.h
include/linux/tick.h
include/linux/uprobes.h
include/linux/usb.h
include/linux/usb/Kbuild
include/linux/usb/audio.h
include/linux/usb/ch9.h
include/linux/usb/functionfs.h
include/linux/wimax/Kbuild [deleted file]
include/media/adv7604.h
include/mtd/Kbuild [deleted file]
include/net/cfg80211.h
include/net/tcp.h
include/net/xfrm.h
include/scsi/scsi_device.h
include/sound/core.h
include/trace/events/gfpflags.h
include/trace/events/xen.h
include/uapi/asm-generic/kvm_para.h
include/uapi/linux/Kbuild
include/uapi/linux/dvb/Kbuild
include/uapi/linux/dvb/audio.h [moved from include/linux/dvb/audio.h with 100% similarity]
include/uapi/linux/dvb/ca.h [moved from include/linux/dvb/ca.h with 100% similarity]
include/uapi/linux/dvb/dmx.h [new file with mode: 0644]
include/uapi/linux/dvb/frontend.h [moved from include/linux/dvb/frontend.h with 100% similarity]
include/uapi/linux/dvb/net.h [moved from include/linux/dvb/net.h with 100% similarity]
include/uapi/linux/dvb/osd.h [moved from include/linux/dvb/osd.h with 100% similarity]
include/uapi/linux/dvb/version.h [moved from include/linux/dvb/version.h with 100% similarity]
include/uapi/linux/dvb/video.h [new file with mode: 0644]
include/uapi/linux/elf-fdpic.h
include/uapi/linux/eventpoll.h
include/uapi/linux/fs.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/hw_breakpoint.h [new file with mode: 0644]
include/uapi/linux/irqnr.h
include/uapi/linux/oom.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/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 100% 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/xen/Kbuild [deleted file]
include/xen/grant_table.h
include/xen/hvm.h
include/xen/interface/grant_table.h
include/xen/interface/memory.h
init/main.c
kernel/Makefile
kernel/cgroup.c
kernel/cpu.c
kernel/events/hw_breakpoint.c
kernel/events/uprobes.c
kernel/futex.c
kernel/irq/irqdomain.c
kernel/modsign_pubkey.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/sched/auto_group.c
kernel/sched/auto_group.h
kernel/sys.c
kernel/time/tick-sched.c
kernel/trace/ring_buffer.c
kernel/watchdog.c
kernel/workqueue.c
lib/Makefile
lib/asn1_decoder.c
lib/dma-debug.c
lib/genalloc.c
lib/mpi/longlong.h
mm/bootmem.c
mm/compaction.c
mm/dmapool.c
mm/fremap.c
mm/highmem.c
mm/huge_memory.c
mm/memblock.c
mm/memcontrol.c
mm/memory-failure.c
mm/memory.c
mm/memory_hotplug.c
mm/mempolicy.c
mm/mmap.c
mm/mmu_notifier.c
mm/mmzone.c
mm/nobootmem.c
mm/page_alloc.c
mm/rmap.c
mm/shmem.c
mm/slob.c
mm/sparse.c
mm/swapfile.c
mm/vmscan.c
net/8021q/vlan.c
net/8021q/vlan_core.c
net/batman-adv/bridge_loop_avoidance.c
net/batman-adv/routing.c
net/batman-adv/soft-interface.c
net/batman-adv/translation-table.c
net/batman-adv/types.h
net/bluetooth/hci_core.c
net/bluetooth/mgmt.c
net/bluetooth/smp.c
net/can/bcm.c
net/ceph/messenger.c
net/core/dev.c
net/core/dev_addr_lists.c
net/core/net-sysfs.c
net/core/rtnetlink.c
net/core/skbuff.c
net/ipv4/icmp.c
net/ipv4/inet_diag.c
net/ipv4/ip_fragment.c
net/ipv4/ip_sockglue.c
net/ipv4/ip_vti.c
net/ipv4/ipmr.c
net/ipv4/netfilter/iptable_nat.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_illinois.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_metrics.c
net/ipv4/tcp_minisocks.c
net/ipv4/tcp_output.c
net/ipv4/tcp_timer.c
net/ipv4/xfrm4_policy.c
net/ipv6/addrconf.c
net/ipv6/inet6_connection_sock.c
net/ipv6/ip6_gre.c
net/ipv6/ipv6_sockglue.c
net/ipv6/ndisc.c
net/ipv6/netfilter/ip6table_nat.c
net/ipv6/netfilter/nf_conntrack_reasm.c
net/ipv6/route.c
net/irda/ircomm/ircomm_tty.c
net/irda/irttp.c
net/l2tp/l2tp_eth.c
net/mac80211/cfg.c
net/mac80211/ibss.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/main.c
net/mac80211/mlme.c
net/mac80211/offchannel.c
net/mac80211/rx.c
net/mac80211/scan.c
net/mac80211/sta_info.c
net/mac80211/status.c
net/mac80211/tx.c
net/mac80211/util.c
net/mac80211/wpa.c
net/netfilter/ipset/ip_set_hash_ip.c
net/netfilter/ipset/ip_set_hash_ipport.c
net/netfilter/ipset/ip_set_hash_ipportip.c
net/netfilter/ipset/ip_set_hash_ipportnet.c
net/netfilter/ipset/ip_set_hash_netiface.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/nf_conntrack_h323_main.c
net/netfilter/nfnetlink_cttimeout.c
net/netfilter/xt_CT.c
net/netfilter/xt_TEE.c
net/netfilter/xt_nat.c
net/netlink/af_netlink.c
net/nfc/llcp/llcp.c
net/openvswitch/flow.c
net/openvswitch/vport-netdev.c
net/sched/sch_qfq.c
net/sctp/chunk.c
net/sctp/proc.c
net/sctp/sm_sideeffect.c
net/sctp/socket.c
net/sctp/transport.c
net/sunrpc/backchannel_rqst.c
net/sunrpc/cache.c
net/sunrpc/xprtsock.c
net/tipc/handler.c
net/wireless/core.c
net/wireless/mlme.c
net/wireless/reg.c
net/wireless/util.c
scripts/Makefile.asm-generic
scripts/Makefile.fwinst
scripts/Makefile.lib
scripts/Makefile.modinst
scripts/Makefile.modpost
scripts/checkpatch.pl
scripts/dtc/Makefile
scripts/dtc/dtc.h
scripts/headers_install.pl
scripts/kconfig/expr.h
scripts/kconfig/list.h [new file with mode: 0644]
scripts/kconfig/lkc_proto.h
scripts/kconfig/mconf.c
scripts/kconfig/menu.c
scripts/sign-file [changed mode: 0644->0755]
scripts/x509keyid [deleted file]
security/apparmor/Makefile
security/apparmor/policy.c
security/device_cgroup.c
security/selinux/hooks.c
security/selinux/netnode.c
sound/core/compress_offload.c
sound/core/control.c
sound/core/hwdep.c
sound/core/init.c
sound/core/oss/mixer_oss.c
sound/core/oss/pcm_oss.c
sound/core/pcm.c
sound/core/pcm_native.c
sound/core/rawmidi.c
sound/core/sound.c
sound/core/sound_oss.c
sound/i2c/other/ak4113.c
sound/i2c/other/ak4114.c
sound/i2c/other/ak4117.c
sound/isa/opti9xx/miro.c
sound/pci/ac97/ac97_codec.c
sound/pci/als300.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/es1968.c
sound/pci/fm801.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_via.c
sound/pci/ice1712/ice1724.c
sound/pci/rme9652/hdspm.c
sound/soc/Makefile
sound/soc/codecs/arizona.c
sound/soc/codecs/cs4271.c
sound/soc/codecs/cs42l52.c
sound/soc/codecs/da9055.c
sound/soc/codecs/twl6040.c
sound/soc/codecs/wm2200.c
sound/soc/codecs/wm5102.c
sound/soc/codecs/wm8978.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm8994.h
sound/soc/kirkwood/kirkwood-dma.c
sound/soc/kirkwood/kirkwood-i2s.c
sound/soc/mxs/mxs-saif.c
sound/soc/omap/ams-delta.c
sound/soc/omap/omap-abe-twl6040.c
sound/soc/omap/omap-dmic.c
sound/soc/omap/omap-mcpdm.c
sound/soc/omap/zoom2.c
sound/soc/pxa/mmp-pcm.c
sound/soc/samsung/Kconfig
sound/soc/samsung/bells.c
sound/soc/sh/fsi.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/soc-jack.c
sound/soc/ux500/mop500.c
sound/soc/ux500/ux500_msp_i2s.c
sound/usb/card.c
sound/usb/card.h
sound/usb/endpoint.c
sound/usb/endpoint.h
sound/usb/midi.c
sound/usb/mixer.c
sound/usb/mixer_quirks.c
sound/usb/pcm.c
sound/usb/proc.c
sound/usb/stream.c
sound/usb/usbaudio.h
tools/Makefile
tools/lib/traceevent/event-parse.c
tools/lib/traceevent/parse-filter.c
tools/perf/Makefile
tools/perf/arch/x86/include/perf_regs.h
tools/perf/builtin-help.c
tools/perf/builtin-kvm.c
tools/perf/builtin-test.c
tools/perf/builtin-trace.c
tools/perf/perf.h
tools/perf/ui/browsers/hists.c
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/header.c
tools/perf/util/header.h
tools/perf/util/parse-events-test.c
tools/perf/util/parse-events.c
tools/perf/util/parse-events.h
tools/perf/util/pmu.h
tools/perf/util/session.h
tools/perf/util/setup.py
tools/perf/util/sort.c
tools/perf/util/strbuf.c
tools/perf/util/thread.c
tools/power/cpupower/.gitignore
tools/power/cpupower/Makefile
tools/power/cpupower/debug/i386/Makefile
tools/power/cpupower/man/cpupower-monitor.1
tools/power/cpupower/utils/helpers/cpuid.c
tools/power/cpupower/utils/helpers/helpers.h
tools/power/cpupower/utils/helpers/sysfs.c
tools/power/cpupower/utils/helpers/topology.c
tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h
tools/power/cpupower/utils/idle_monitor/snb_idle.c
tools/power/x86/turbostat/turbostat.c
tools/scripts/Makefile.include
tools/testing/ktest/ktest.pl
tools/testing/selftests/Makefile
tools/testing/selftests/epoll/Makefile [deleted file]
tools/testing/selftests/epoll/test_epoll.c [deleted file]
tools/vm/page-types.c
usr/gen_init_cpio.c
virt/kvm/kvm_main.c

index 0f2f40f..92bd0e4 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 d8fe12a..2346b09 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1823,6 +1823,11 @@ S: Kattreinstr 38
 S: D-64295
 S: Germany
 
+N: Avi Kivity
+E: avi.kivity@gmail.com
+D: Kernel-based Virtual Machine (KVM)
+S: Ra'annana, Israel
+
 N: Andi Kleen
 E: andi@firstfloor.org
 U: http://www.halobates.de
index f54273e..ceb1ff7 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 23d78b5..0ba6ea2 100644 (file)
@@ -11,7 +11,7 @@ What:         /sys/class/devfreq/.../governor
 Date:          September 2011
 Contact:       MyungJoo Ham <myungjoo.ham@samsung.com>
 Description:
-               The /sys/class/devfreq/.../governor shows the name of the
+               The /sys/class/devfreq/.../governor show or set the name of the
                governor used by the corresponding devfreq object.
 
 What:          /sys/class/devfreq/.../cur_freq
@@ -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
@@ -43,6 +44,17 @@ Description:
                (/sys/class/devfreq/.../central_polling is 0), this value
                may be useless.
 
+What:          /sys/class/devfreq/.../trans_stat
+Date:          October 2012
+Contact:       MyungJoo Ham <myungjoo.ham@samsung.com>
+Descrtiption:
+               This ABI shows the statistics of devfreq behavior on a
+               specific device. It shows the time spent in each state and
+               the number of transitions between states.
+               In order to activate this ABI, the devfreq target device
+               driver should provide the list of available frequencies
+               with its profile.
+
 What:          /sys/class/devfreq/.../userspace/set_freq
 Date:          September 2011
 Contact:       MyungJoo Ham <myungjoo.ham@samsung.com>
@@ -50,3 +62,19 @@ Description:
                The /sys/class/devfreq/.../userspace/set_freq shows and
                sets the requested frequency for the devfreq object if
                userspace governor is in effect.
+
+What:          /sys/class/devfreq/.../available_frequencies
+Date:          October 2012
+Contact:       Nishanth Menon <nm@ti.com>
+Description:
+               The /sys/class/devfreq/.../available_frequencies shows
+               the available frequencies of the corresponding devfreq object.
+               This is a snapshot of available frequencies and not limited
+               by the min/max frequency restrictions.
+
+What:          /sys/class/devfreq/.../available_governors
+Date:          October 2012
+Contact:       Nishanth Menon <nm@ti.com>
+Description:
+               The /sys/class/devfreq/.../available_governors shows
+               currently available governors in the system.
index 45000f0..7fc2997 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.
diff --git a/Documentation/ABI/testing/sysfs-devices-sun b/Documentation/ABI/testing/sysfs-devices-sun
new file mode 100644 (file)
index 0000000..86be984
--- /dev/null
@@ -0,0 +1,14 @@
+Whatt:         /sys/devices/.../sun
+Date:          October 2012
+Contact:       Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
+Description:
+               The file contains a Slot-unique ID which provided by the _SUN
+               method in the ACPI namespace. The value is written in Advanced
+               Configuration and Power Interface Specification as follows:
+
+               "The _SUN value is required to be unique among the slots of
+               the same type. It is also recommended that this number match
+               the slot number printed on the physical slot whenever possible."
+
+               So reading the sysfs file, we can identify a physical position
+               of the slot in the system.
index 9b7e4c5..f9fd615 100644 (file)
@@ -56,15 +56,15 @@ FUNCS = \
        write \
 
 IOCTLS = \
-       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/videodev2.h) \
-       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/dvb/audio.h) \
-       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/dvb/ca.h) \
-       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/dvb/dmx.h) \
-       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/dvb/frontend.h) \
-       $(shell perl -ne 'print "$$1 " if /\#define\s+([A-Z][^\s]+)\s+_IO/' $(srctree)/include/linux/dvb/net.h) \
-       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/dvb/video.h) \
-       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/media.h) \
-       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/v4l2-subdev.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/videodev2.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/audio.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/ca.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/dmx.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/frontend.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([A-Z][^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/net.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/video.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/media.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/v4l2-subdev.h) \
        VIDIOC_SUBDEV_G_FRAME_INTERVAL \
        VIDIOC_SUBDEV_S_FRAME_INTERVAL \
        VIDIOC_SUBDEV_ENUM_MBUS_CODE \
@@ -74,32 +74,32 @@ IOCTLS = \
        VIDIOC_SUBDEV_S_SELECTION \
 
 TYPES = \
-       $(shell perl -ne 'print "$$1 " if /^typedef\s+[^\s]+\s+([^\s]+)\;/' $(srctree)/include/linux/videodev2.h) \
-       $(shell perl -ne 'print "$$1 " if /^}\s+([a-z0-9_]+_t)/' $(srctree)/include/linux/dvb/frontend.h)
+       $(shell perl -ne 'print "$$1 " if /^typedef\s+[^\s]+\s+([^\s]+)\;/' $(srctree)/include/uapi/linux/videodev2.h) \
+       $(shell perl -ne 'print "$$1 " if /^}\s+([a-z0-9_]+_t)/' $(srctree)/include/uapi/linux/dvb/frontend.h)
 
 ENUMS = \
-       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/videodev2.h) \
-       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/dvb/audio.h) \
-       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/dvb/ca.h) \
-       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/dvb/dmx.h) \
-       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/dvb/frontend.h) \
-       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/dvb/net.h) \
-       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/dvb/video.h) \
-       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/media.h) \
-       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/v4l2-mediabus.h) \
-       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/v4l2-subdev.h)
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/videodev2.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/dvb/audio.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/dvb/ca.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/dvb/dmx.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/dvb/frontend.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/dvb/net.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/dvb/video.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/media.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/v4l2-mediabus.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/v4l2-subdev.h)
 
 STRUCTS = \
-       $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/linux/videodev2.h) \
-       $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s\{]+)\s*/)' $(srctree)/include/linux/dvb/audio.h) \
-       $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/linux/dvb/ca.h) \
-       $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/linux/dvb/dmx.h) \
-       $(shell perl -ne 'print "$$1 " if (!/dtv\_cmds\_h/ && /^struct\s+([^\s]+)\s+/)' $(srctree)/include/linux/dvb/frontend.h) \
-       $(shell perl -ne 'print "$$1 " if (/^struct\s+([A-Z][^\s]+)\s+/)' $(srctree)/include/linux/dvb/net.h) \
-       $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/linux/dvb/video.h) \
-       $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/linux/media.h) \
-       $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/linux/v4l2-subdev.h) \
-       $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/linux/v4l2-mediabus.h)
+       $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/videodev2.h) \
+       $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s\{]+)\s*/)' $(srctree)/include/uapi/linux/dvb/audio.h) \
+       $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/uapi/linux/dvb/ca.h) \
+       $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/uapi/linux/dvb/dmx.h) \
+       $(shell perl -ne 'print "$$1 " if (!/dtv\_cmds\_h/ && /^struct\s+([^\s]+)\s+/)' $(srctree)/include/uapi/linux/dvb/frontend.h) \
+       $(shell perl -ne 'print "$$1 " if (/^struct\s+([A-Z][^\s]+)\s+/)' $(srctree)/include/uapi/linux/dvb/net.h) \
+       $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/uapi/linux/dvb/video.h) \
+       $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/media.h) \
+       $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/v4l2-subdev.h) \
+       $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/v4l2-mediabus.h)
 
 ERRORS = \
        E2BIG \
@@ -205,7 +205,7 @@ $(MEDIA_OBJ_DIR)/v4l2.xml: $(OBJIMGFILES)
        @(ln -sf $(MEDIA_SRC_DIR)/v4l/*xml $(MEDIA_OBJ_DIR)/)
        @(ln -sf $(MEDIA_SRC_DIR)/dvb/*xml $(MEDIA_OBJ_DIR)/)
 
-$(MEDIA_OBJ_DIR)/videodev2.h.xml: $(srctree)/include/linux/videodev2.h $(MEDIA_OBJ_DIR)/v4l2.xml
+$(MEDIA_OBJ_DIR)/videodev2.h.xml: $(srctree)/include/uapi/linux/videodev2.h $(MEDIA_OBJ_DIR)/v4l2.xml
        @$($(quiet)gen_xml)
        @(                                      \
        echo "<programlisting>") > $@
@@ -216,7 +216,7 @@ $(MEDIA_OBJ_DIR)/videodev2.h.xml: $(srctree)/include/linux/videodev2.h $(MEDIA_O
        @(                                      \
        echo "</programlisting>") >> $@
 
-$(MEDIA_OBJ_DIR)/audio.h.xml: $(srctree)/include/linux/dvb/audio.h $(MEDIA_OBJ_DIR)/v4l2.xml
+$(MEDIA_OBJ_DIR)/audio.h.xml: $(srctree)/include/uapi/linux/dvb/audio.h $(MEDIA_OBJ_DIR)/v4l2.xml
        @$($(quiet)gen_xml)
        @(                                      \
        echo "<programlisting>") > $@
@@ -227,7 +227,7 @@ $(MEDIA_OBJ_DIR)/audio.h.xml: $(srctree)/include/linux/dvb/audio.h $(MEDIA_OBJ_D
        @(                                      \
        echo "</programlisting>") >> $@
 
-$(MEDIA_OBJ_DIR)/ca.h.xml: $(srctree)/include/linux/dvb/ca.h $(MEDIA_OBJ_DIR)/v4l2.xml
+$(MEDIA_OBJ_DIR)/ca.h.xml: $(srctree)/include/uapi/linux/dvb/ca.h $(MEDIA_OBJ_DIR)/v4l2.xml
        @$($(quiet)gen_xml)
        @(                                      \
        echo "<programlisting>") > $@
@@ -238,7 +238,7 @@ $(MEDIA_OBJ_DIR)/ca.h.xml: $(srctree)/include/linux/dvb/ca.h $(MEDIA_OBJ_DIR)/v4
        @(                                      \
        echo "</programlisting>") >> $@
 
-$(MEDIA_OBJ_DIR)/dmx.h.xml: $(srctree)/include/linux/dvb/dmx.h $(MEDIA_OBJ_DIR)/v4l2.xml
+$(MEDIA_OBJ_DIR)/dmx.h.xml: $(srctree)/include/uapi/linux/dvb/dmx.h $(MEDIA_OBJ_DIR)/v4l2.xml
        @$($(quiet)gen_xml)
        @(                                      \
        echo "<programlisting>") > $@
@@ -249,7 +249,7 @@ $(MEDIA_OBJ_DIR)/dmx.h.xml: $(srctree)/include/linux/dvb/dmx.h $(MEDIA_OBJ_DIR)/
        @(                                      \
        echo "</programlisting>") >> $@
 
-$(MEDIA_OBJ_DIR)/frontend.h.xml: $(srctree)/include/linux/dvb/frontend.h $(MEDIA_OBJ_DIR)/v4l2.xml
+$(MEDIA_OBJ_DIR)/frontend.h.xml: $(srctree)/include/uapi/linux/dvb/frontend.h $(MEDIA_OBJ_DIR)/v4l2.xml
        @$($(quiet)gen_xml)
        @(                                      \
        echo "<programlisting>") > $@
@@ -260,7 +260,7 @@ $(MEDIA_OBJ_DIR)/frontend.h.xml: $(srctree)/include/linux/dvb/frontend.h $(MEDIA
        @(                                      \
        echo "</programlisting>") >> $@
 
-$(MEDIA_OBJ_DIR)/net.h.xml: $(srctree)/include/linux/dvb/net.h $(MEDIA_OBJ_DIR)/v4l2.xml
+$(MEDIA_OBJ_DIR)/net.h.xml: $(srctree)/include/uapi/linux/dvb/net.h $(MEDIA_OBJ_DIR)/v4l2.xml
        @$($(quiet)gen_xml)
        @(                                      \
        echo "<programlisting>") > $@
@@ -271,7 +271,7 @@ $(MEDIA_OBJ_DIR)/net.h.xml: $(srctree)/include/linux/dvb/net.h $(MEDIA_OBJ_DIR)/
        @(                                      \
        echo "</programlisting>") >> $@
 
-$(MEDIA_OBJ_DIR)/video.h.xml: $(srctree)/include/linux/dvb/video.h $(MEDIA_OBJ_DIR)/v4l2.xml
+$(MEDIA_OBJ_DIR)/video.h.xml: $(srctree)/include/uapi/linux/dvb/video.h $(MEDIA_OBJ_DIR)/v4l2.xml
        @$($(quiet)gen_xml)
        @(                                      \
        echo "<programlisting>") > $@
index 59ad69a..29df250 100644 (file)
@@ -56,7 +56,7 @@
 !Enet/core/filter.c
      </sect1>
      <sect1><title>Generic Network Statistics</title>
-!Iinclude/linux/gen_stats.h
+!Iinclude/uapi/linux/gen_stats.h
 !Enet/core/gen_stats.c
 !Enet/core/gen_estimator.c
      </sect1>
@@ -80,7 +80,7 @@
 !Enet/wimax/op-rfkill.c
 !Enet/wimax/stack.c
 !Iinclude/net/wimax.h
-!Iinclude/linux/wimax.h
+!Iinclude/uapi/linux/wimax.h
      </sect1>
   </chapter>
 
index b2bea15..16eb4c9 100644 (file)
@@ -42,13 +42,7 @@ The driver interface depends on your hardware.  If your system
 properly provides the SMBIOS info for IPMI, the driver will detect it
 and just work.  If you have a board with a standard interface (These
 will generally be either "KCS", "SMIC", or "BT", consult your hardware
-manual), choose the 'IPMI SI handler' option.  A driver also exists
-for direct I2C access to the IPMI management controller.  Some boards
-support this, but it is unknown if it will work on every board.  For
-this, choose 'IPMI SMBus handler', but be ready to try to do some
-figuring to see if it will work on your system if the SMBIOS/APCI
-information is wrong or not present.  It is fairly safe to have both
-these enabled and let the drivers auto-detect what is present.
+manual), choose the 'IPMI SI handler' option.
 
 You should generally enable ACPI on your system, as systems with IPMI
 can have ACPI tables describing them.
@@ -58,8 +52,7 @@ their job correctly, the IPMI controller should be automatically
 detected (via ACPI or SMBIOS tables) and should just work.  Sadly,
 many boards do not have this information.  The driver attempts
 standard defaults, but they may not work.  If you fall into this
-situation, you need to read the section below named 'The SI Driver' or
-"The SMBus Driver" on how to hand-configure your system.
+situation, you need to read the section below named 'The SI Driver'.
 
 IPMI defines a standard watchdog timer.  You can enable this with the
 'IPMI Watchdog Timer' config option.  If you compile the driver into
@@ -104,12 +97,7 @@ driver, each open file for this device ties in to the message handler
 as an IPMI user.
 
 ipmi_si - A driver for various system interfaces.  This supports KCS,
-SMIC, and BT interfaces.  Unless you have an SMBus interface or your
-own custom interface, you probably need to use this.
-
-ipmi_smb - A driver for accessing BMCs on the SMBus. It uses the
-I2C kernel driver's SMBus interfaces to send and receive IPMI messages
-over the SMBus.
+SMIC, and BT interfaces.
 
 ipmi_watchdog - IPMI requires systems to have a very capable watchdog
 timer.  This driver implements the standard Linux watchdog timer
@@ -482,53 +470,6 @@ for specifying an interface.  Note that when removing an interface,
 only the first three parameters (si type, address type, and address)
 are used for the comparison.  Any options are ignored for removing.
 
-The SMBus Driver
-----------------
-
-The SMBus driver allows up to 4 SMBus devices to be configured in the
-system.  By default, the driver will register any SMBus interfaces it finds
-in the I2C address range of 0x20 to 0x4f on any adapter.  You can change this
-at module load time (for a module) with:
-
-  modprobe ipmi_smb.o
-       addr=<adapter1>,<i2caddr1>[,<adapter2>,<i2caddr2>[,...]]
-       dbg=<flags1>,<flags2>...
-       [defaultprobe=1] [dbg_probe=1]
-
-The addresses are specified in pairs, the first is the adapter ID and the
-second is the I2C address on that adapter.
-
-The debug flags are bit flags for each BMC found, they are:
-IPMI messages: 1, driver state: 2, timing: 4, I2C probe: 8
-
-Setting smb_defaultprobe to zero disabled the default probing of SMBus
-interfaces at address range 0x20 to 0x4f.  This means that only the
-BMCs specified on the smb_addr line will be detected.
-
-Setting smb_dbg_probe to 1 will enable debugging of the probing and
-detection process for BMCs on the SMBusses.
-
-Discovering the IPMI compliant BMC on the SMBus can cause devices
-on the I2C bus to fail. The SMBus driver writes a "Get Device ID" IPMI
-message as a block write to the I2C bus and waits for a response.
-This action can be detrimental to some I2C devices. It is highly recommended
-that the known I2c address be given to the SMBus driver in the smb_addr
-parameter. The default address range will not be used when a smb_addr
-parameter is provided.
-
-When compiled into the kernel, the addresses can be specified on the
-kernel command line as:
-
-  ipmb_smb.addr=<adapter1>,<i2caddr1>[,<adapter2>,<i2caddr2>[,...]]
-       ipmi_smb.dbg=<flags1>,<flags2>...
-       ipmi_smb.defaultprobe=0 ipmi_smb.dbg_probe=1
-
-These are the same options as on the module command line.
-
-Note that you might need some I2C changes if CONFIG_IPMI_PANIC_EVENT
-is enabled along with this, so the I2C driver knows to run to
-completion during sending a panic event.
-
 
 Other Pieces
 ------------
index 1401cec..9bc9594 100644 (file)
@@ -7,6 +7,21 @@ systems with multiple interrupt controllers the kernel must ensure
 that each one gets assigned non-overlapping allocations of Linux
 IRQ numbers.
 
+The number of interrupt controllers registered as unique irqchips
+show a rising tendency: for example subdrivers of different kinds
+such as GPIO controllers avoid reimplementing identical callback
+mechanisms as the IRQ core system by modelling their interrupt
+handlers as irqchips, i.e. in effect cascading interrupt controllers.
+
+Here the interrupt number loose all kind of correspondence to
+hardware interrupt numbers: whereas in the past, IRQ numbers could
+be chosen so they matched the hardware IRQ line into the root
+interrupt controller (i.e. the component actually fireing the
+interrupt line to the CPU) nowadays this number is just a number.
+
+For this reason we need a mechanism to separate controller-local
+interrupt numbers, called hardware irq's, from Linux IRQ numbers.
+
 The irq_alloc_desc*() and irq_free_desc*() APIs provide allocation of
 irq numbers, but they don't provide any support for reverse mapping of
 the controller-local IRQ (hwirq) number into the Linux IRQ number
@@ -40,6 +55,10 @@ required hardware setup.
 When an interrupt is received, irq_find_mapping() function should
 be used to find the Linux IRQ number from the hwirq number.
 
+The irq_create_mapping() function must be called *atleast once*
+before any call to irq_find_mapping(), lest the descriptor will not
+be allocated.
+
 If the driver has the Linux IRQ number or the irq_data pointer, and
 needs to know the associated hwirq number (such as in the irq_chip
 callbacks) then it can be directly obtained from irq_data->hwirq.
@@ -119,4 +138,17 @@ numbers.
 
 Most users of legacy mappings should use irq_domain_add_simple() which
 will use a legacy domain only if an IRQ range is supplied by the
-system and will otherwise use a linear domain mapping.
+system and will otherwise use a linear domain mapping. The semantics
+of this call are such that if an IRQ range is specified then
+descriptors will be allocated on-the-fly for it, and if no range is
+specified it will fall through to irq_domain_add_linear() which meand
+*no* irq descriptors will be allocated.
+
+A typical use case for simple domains is where an irqchip provider
+is supporting both dynamic and static IRQ assignments.
+
+In order to avoid ending up in a situation where a linear domain is
+used and no descriptor gets allocated it is very important to make sure
+that the driver using the simple domain call irq_create_mapping()
+before any irq_find_mapping() since the latter will actually work
+for the static IRQ assignment case.
diff --git a/Documentation/acpi/enumeration.txt b/Documentation/acpi/enumeration.txt
new file mode 100644 (file)
index 0000000..4f27785
--- /dev/null
@@ -0,0 +1,227 @@
+ACPI based device enumeration
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ACPI 5 introduced a set of new resources (UartTSerialBus, I2cSerialBus,
+SpiSerialBus, GpioIo and GpioInt) which can be used in enumerating slave
+devices behind serial bus controllers.
+
+In addition we are starting to see peripherals integrated in the
+SoC/Chipset to appear only in ACPI namespace. These are typically devices
+that are accessed through memory-mapped registers.
+
+In order to support this and re-use the existing drivers as much as
+possible we decided to do following:
+
+       o Devices that have no bus connector resource are represented as
+         platform devices.
+
+       o Devices behind real busses where there is a connector resource
+         are represented as struct spi_device or struct i2c_device
+         (standard UARTs are not busses so there is no struct uart_device).
+
+As both ACPI and Device Tree represent a tree of devices (and their
+resources) this implementation follows the Device Tree way as much as
+possible.
+
+The ACPI implementation enumerates devices behind busses (platform, SPI and
+I2C), creates the physical devices and binds them to their ACPI handle in
+the ACPI namespace.
+
+This means that when ACPI_HANDLE(dev) returns non-NULL the device was
+enumerated from ACPI namespace. This handle can be used to extract other
+device-specific configuration. There is an example of this below.
+
+Platform bus support
+~~~~~~~~~~~~~~~~~~~~
+Since we are using platform devices to represent devices that are not
+connected to any physical bus we only need to implement a platform driver
+for the device and add supported ACPI IDs. If this same IP-block is used on
+some other non-ACPI platform, the driver might work out of the box or needs
+some minor changes.
+
+Adding ACPI support for an existing driver should be pretty
+straightforward. Here is the simplest example:
+
+       #ifdef CONFIG_ACPI
+       static struct acpi_device_id mydrv_acpi_match[] = {
+               /* ACPI IDs here */
+               { }
+       };
+       MODULE_DEVICE_TABLE(acpi, mydrv_acpi_match);
+       #endif
+
+       static struct platform_driver my_driver = {
+               ...
+               .driver = {
+                       .acpi_match_table = ACPI_PTR(mydrv_acpi_match),
+               },
+       };
+
+If the driver needs to perform more complex initialization like getting and
+configuring GPIOs it can get its ACPI handle and extract this information
+from ACPI tables.
+
+Currently the kernel is not able to automatically determine from which ACPI
+device it should make the corresponding platform device so we need to add
+the ACPI device explicitly to acpi_platform_device_ids list defined in
+drivers/acpi/scan.c. This limitation is only for the platform devices, SPI
+and I2C devices are created automatically as described below.
+
+SPI serial bus support
+~~~~~~~~~~~~~~~~~~~~~~
+Slave devices behind SPI bus have SpiSerialBus resource attached to them.
+This is extracted automatically by the SPI core and the slave devices are
+enumerated once spi_register_master() is called by the bus driver.
+
+Here is what the ACPI namespace for a SPI slave might look like:
+
+       Device (EEP0)
+       {
+               Name (_ADR, 1)
+               Name (_CID, Package() {
+                       "ATML0025",
+                       "AT25",
+               })
+               ...
+               Method (_CRS, 0, NotSerialized)
+               {
+                       SPISerialBus(1, PolarityLow, FourWireMode, 8,
+                               ControllerInitiated, 1000000, ClockPolarityLow,
+                               ClockPhaseFirst, "\\_SB.PCI0.SPI1",)
+               }
+               ...
+
+The SPI device drivers only need to add ACPI IDs in a similar way than with
+the platform device drivers. Below is an example where we add ACPI support
+to at25 SPI eeprom driver (this is meant for the above ACPI snippet):
+
+       #ifdef CONFIG_ACPI
+       static struct acpi_device_id at25_acpi_match[] = {
+               { "AT25", 0 },
+               { },
+       };
+       MODULE_DEVICE_TABLE(acpi, at25_acpi_match);
+       #endif
+
+       static struct spi_driver at25_driver = {
+               .driver = {
+                       ...
+                       .acpi_match_table = ACPI_PTR(at25_acpi_match),
+               },
+       };
+
+Note that this driver actually needs more information like page size of the
+eeprom etc. but at the time writing this there is no standard way of
+passing those. One idea is to return this in _DSM method like:
+
+       Device (EEP0)
+       {
+               ...
+               Method (_DSM, 4, NotSerialized)
+               {
+                       Store (Package (6)
+                       {
+                               "byte-len", 1024,
+                               "addr-mode", 2,
+                               "page-size, 32
+                       }, Local0)
+
+                       // Check UUIDs etc.
+
+                       Return (Local0)
+               }
+
+Then the at25 SPI driver can get this configation by calling _DSM on its
+ACPI handle like:
+
+       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+       struct acpi_object_list input;
+       acpi_status status;
+
+       /* Fill in the input buffer */
+
+       status = acpi_evaluate_object(ACPI_HANDLE(&spi->dev), "_DSM",
+                                     &input, &output);
+       if (ACPI_FAILURE(status))
+               /* Handle the error */
+
+       /* Extract the data here */
+
+       kfree(output.pointer);
+
+I2C serial bus support
+~~~~~~~~~~~~~~~~~~~~~~
+The slaves behind I2C bus controller only need to add the ACPI IDs like
+with the platform and SPI drivers. However the I2C bus controller driver
+needs to call acpi_i2c_register_devices() after it has added the adapter.
+
+An I2C bus (controller) driver does:
+
+       ...
+       ret = i2c_add_numbered_adapter(adapter);
+       if (ret)
+               /* handle error */
+
+       of_i2c_register_devices(adapter);
+       /* Enumerate the slave devices behind this bus via ACPI */
+       acpi_i2c_register_devices(adapter);
+
+Below is an example of how to add ACPI support to the existing mpu3050
+input driver:
+
+       #ifdef CONFIG_ACPI
+       static struct acpi_device_id mpu3050_acpi_match[] = {
+               { "MPU3050", 0 },
+               { },
+       };
+       MODULE_DEVICE_TABLE(acpi, mpu3050_acpi_match);
+       #endif
+
+       static struct i2c_driver mpu3050_i2c_driver = {
+               .driver = {
+                       .name   = "mpu3050",
+                       .owner  = THIS_MODULE,
+                       .pm     = &mpu3050_pm,
+                       .of_match_table = mpu3050_of_match,
+                       .acpi_match_table  ACPI_PTR(mpu3050_acpi_match),
+               },
+               .probe          = mpu3050_probe,
+               .remove         = __devexit_p(mpu3050_remove),
+               .id_table       = mpu3050_ids,
+       };
+
+GPIO support
+~~~~~~~~~~~~
+ACPI 5 introduced two new resources to describe GPIO connections: GpioIo
+and GpioInt. These resources are used be used to pass GPIO numbers used by
+the device to the driver. For example:
+
+       Method (_CRS, 0, NotSerialized)
+       {
+               Name (SBUF, ResourceTemplate()
+               {
+                       GpioIo (Exclusive, PullDefault, 0x0000, 0x0000,
+                               IoRestrictionOutputOnly, "\\_SB.PCI0.GPI0",
+                               0x00, ResourceConsumer,,)
+                       {
+                               // Pin List
+                               0x0055
+                       }
+                       ...
+
+                       Return (SBUF)
+               }
+       }
+
+These GPIO numbers are controller relative and path "\\_SB.PCI0.GPI0"
+specifies the path to the controller. In order to use these GPIOs in Linux
+we need to translate them to the Linux GPIO numbers.
+
+The driver can do this by including <linux/acpi_gpio.h> and then calling
+acpi_get_gpio(path, gpio). This will return the Linux GPIO number or
+negative errno if there was no translation found.
+
+Other GpioIo parameters must be converted first by the driver to be
+suitable to the gpiolib before passing them.
+
+In case of GpioInt resource an additional call to gpio_to_irq() must be
+done before calling request_irq().
index dbbdcbb..4110cca 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 c07f7b4..71c4da4 100644 (file)
@@ -466,6 +466,10 @@ Note:
 5.3 swappiness
 
 Similar to /proc/sys/vm/swappiness, but affecting a hierarchy of groups only.
+Please note that unlike the global swappiness, memcg knob set to 0
+really prevents from any swapping even if there is a swap storage
+available. This might lead to memcg OOM killer if there are no file
+pages to reclaim.
 
 Following cgroups' swappiness can't be changed.
 - root cgroup (uses /proc/sys/vm/swappiness).
index ecc81e3..1196290 100644 (file)
@@ -7,8 +7,14 @@ PIT Timer required properties:
 - interrupts: Should contain interrupt for the PIT which is the IRQ line
   shared across all System Controller members.
 
+System Timer (ST) required properties:
+- compatible: Should be "atmel,at91rm9200-st"
+- reg: Should contain registers location and length
+- interrupts: Should contain interrupt for the ST which is the IRQ line
+  shared across all System Controller members.
+
 TC/TCLIB Timer required properties:
-- compatible: Should be "atmel,<chip>-pit".
+- compatible: Should be "atmel,<chip>-tcb".
   <chip> can be "at91rm9200" or "at91sam9x5"
 - reg: Should contain registers location and length
 - interrupts: Should contain all interrupts for the TC block
index e37241f..49fc7ad 100644 (file)
@@ -23,29 +23,16 @@ Recommended properties :
 - ti,davinci-nand-buswidth: buswidth 8 or 16
 - ti,davinci-nand-use-bbt: use flash based bad block table support.
 
-Example (enbw_cmc board):
-aemif@60000000 {
-       compatible = "ti,davinci-aemif";
-       #address-cells = <2>;
-       #size-cells = <1>;
-       reg = <0x68000000 0x80000>;
-       ranges = <2 0 0x60000000 0x02000000
-                 3 0 0x62000000 0x02000000
-                 4 0 0x64000000 0x02000000
-                 5 0 0x66000000 0x02000000
-                 6 0 0x68000000 0x02000000>;
-       nand@3,0 {
-               compatible = "ti,davinci-nand";
-               reg = <3 0x0 0x807ff
-                       6 0x0 0x8000>;
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ti,davinci-chipselect = <1>;
-               ti,davinci-mask-ale = <0>;
-               ti,davinci-mask-cle = <0>;
-               ti,davinci-mask-chipsel = <0>;
-               ti,davinci-ecc-mode = "hw";
-               ti,davinci-ecc-bits = <4>;
-               ti,davinci-nand-use-bbt;
-       };
+Example(da850 EVM ):
+nand_cs3@62000000 {
+       compatible = "ti,davinci-nand";
+       reg = <0x62000000 0x807ff
+               0x68000000 0x8000>;
+       ti,davinci-chipselect = <1>;
+       ti,davinci-mask-ale = <0>;
+       ti,davinci-mask-cle = <0>;
+       ti,davinci-mask-chipsel = <0>;
+       ti,davinci-ecc-mode = "hw";
+       ti,davinci-ecc-bits = <4>;
+       ti,davinci-nand-use-bbt;
 };
index 7ca5216..7c3ee3a 100644 (file)
@@ -37,7 +37,7 @@ L2: cache-controller {
         reg = <0xfff12000 0x1000>;
         arm,data-latency = <1 1 1>;
         arm,tag-latency = <2 2 2>;
-        arm,filter-latency = <0x80000000 0x8000000>;
+        arm,filter-ranges = <0x80000000 0x8000000>;
         cache-unified;
         cache-level = <2>;
        interrupts = <45>;
index a0b867e..baadbb1 100644 (file)
@@ -52,7 +52,7 @@ clocks and IDs.
        lcdif           38
        etm             39
        usb             40
-       usb_pwr         41
+       usb_phy         41
 
 Examples:
 
index aa2af28..52a49a4 100644 (file)
@@ -73,8 +73,8 @@ clocks and IDs.
        can1            59
        usb0            60
        usb1            61
-       usb0_pwr        62
-       usb1_pwr        63
+       usb0_phy        62
+       usb1_phy        63
        enet_out        64
 
 Examples:
diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-spear.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-spear.txt
new file mode 100644 (file)
index 0000000..f3d4498
--- /dev/null
@@ -0,0 +1,42 @@
+SPEAr cpufreq driver
+-------------------
+
+SPEAr SoC cpufreq driver for CPU frequency scaling.
+It supports both uniprocessor (UP) and symmetric multiprocessor (SMP) systems
+which share clock across all CPUs.
+
+Required properties:
+- cpufreq_tbl: Table of frequencies CPU could be transitioned into, in the
+  increasing order.
+
+Optional properties:
+- clock-latency: Specify the possible maximum transition latency for clock, in
+  unit of nanoseconds.
+
+Both required and optional properties listed above must be defined under node
+/cpus/cpu@0.
+
+Examples:
+--------
+cpus {
+
+       <...>
+
+       cpu@0 {
+               compatible = "arm,cortex-a9";
+               reg = <0>;
+
+               <...>
+
+               cpufreq_tbl = < 166000
+                               200000
+                               250000
+                               300000
+                               400000
+                               500000
+                               600000 >;
+       };
+
+       <...>
+
+};
index 4e16ba4..a336287 100644 (file)
@@ -75,4 +75,40 @@ Example of two SOC GPIO banks defined as gpio-controller nodes:
                gpio-controller;
        };
 
+2.1) gpio-controller and pinctrl subsystem
+------------------------------------------
 
+gpio-controller on a SOC might be tightly coupled with the pinctrl
+subsystem, in the sense that the pins can be used by other functions
+together with optional gpio feature.
+
+While the pin allocation is totally managed by the pin ctrl subsystem,
+gpio (under gpiolib) is still maintained by gpio drivers. It may happen
+that different pin ranges in a SoC is managed by different gpio drivers.
+
+This makes it logical to let gpio drivers announce their pin ranges to
+the pin ctrl subsystem and call 'pinctrl_request_gpio' in order to
+request the corresponding pin before any gpio usage.
+
+For this, the gpio controller can use a pinctrl phandle and pins to
+announce the pinrange to the pin ctrl subsystem. For example,
+
+       qe_pio_e: gpio-controller@1460 {
+               #gpio-cells = <2>;
+               compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
+               reg = <0x1460 0x18>;
+               gpio-controller;
+               gpio-ranges = <&pinctrl1 20 10>, <&pinctrl2 50 20>;
+
+    }
+
+where,
+   &pinctrl1 and &pinctrl2 is the phandle to the pinctrl DT node.
+
+   Next values specify the base pin and number of pins for the range
+   handled by 'qe_pio_e' gpio. In the given example from base pin 20 to
+   pin 29 under pinctrl1 and pin 50 to pin 69 under pinctrl2 is handled
+   by this gpio controller.
+
+The pinctrl node must have "#gpio-range-cells" property to show number of
+arguments to pass with phandle from gpio controllers node.
index 66efc80..85f8c0d 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>;
        };
 
diff --git a/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt b/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt
new file mode 100644 (file)
index 0000000..f46d928
--- /dev/null
@@ -0,0 +1,18 @@
+
+* Marvell MV64XXX I2C controller
+
+Required properties :
+
+ - reg             : Offset and length of the register set for the device
+ - compatible      : Should be "marvell,mv64xxx-i2c"
+ - interrupts      : The interrupt number
+ - clock-frequency : Desired I2C bus clock frequency in Hz.
+
+Examples:
+
+       i2c@11000 {
+               compatible = "marvell,mv64xxx-i2c";
+               reg = <0x11000 0x20>;
+               interrupts = <29>;
+               clock-frequency = <100000>;
+       };
@@ -31,21 +31,3 @@ Examples:
                reg = <0xd4025000 0x1000>;
                interrupts = <58>;
        };
-
-* Marvell MV64XXX I2C controller
-
-Required properties :
-
- - reg             : Offset and length of the register set for the device
- - compatible      : Should be "marvell,mv64xxx-i2c"
- - interrupts      : The interrupt number
- - clock-frequency : Desired I2C bus clock frequency in Hz.
-
-Examples:
-
-       i2c@11000 {
-               compatible = "marvell,mv64xxx-i2c";
-               reg = <0x11000 0x20>;
-               interrupts = <29>;
-               clock-frequency = <100000>;
-       };
diff --git a/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt
new file mode 100644 (file)
index 0000000..df70318
--- /dev/null
@@ -0,0 +1,19 @@
+* EETI eGalax Multiple Touch Controller
+
+Required properties:
+- compatible: must be "eeti,egalax_ts"
+- reg: i2c slave address
+- interrupt-parent: the phandle for the interrupt controller
+- interrupts: touch controller interrupt
+- wakeup-gpios: the gpio pin to be used for waking up the controller
+  as well as uased as irq pin
+
+Example:
+
+       egalax_ts@04 {
+               compatible = "eeti,egalax_ts";
+               reg = <0x04>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <9 2>;
+               wakeup-gpios = <&gpio1 9 0>;
+       };
diff --git a/Documentation/devicetree/bindings/leds/common.txt b/Documentation/devicetree/bindings/leds/common.txt
new file mode 100644 (file)
index 0000000..2d88816
--- /dev/null
@@ -0,0 +1,23 @@
+Common leds properties.
+
+Optional properties for child nodes:
+- label : The label for this LED.  If omitted, the label is
+  taken from the node name (excluding the unit address).
+
+- linux,default-trigger :  This parameter, if present, is a
+    string defining the trigger assigned to the LED.  Current triggers are:
+     "backlight" - LED will act as a back-light, controlled by the framebuffer
+                  system
+     "default-on" - LED will turn on (but for leds-gpio see "default-state"
+                   property in Documentation/devicetree/bindings/gpio/led.txt)
+     "heartbeat" - LED "double" flashes at a load average based rate
+     "ide-disk" - LED indicates disk activity
+     "timer" - LED flashes at a fixed, configurable rate
+
+Examples:
+
+system-status {
+       label = "Status";
+       linux,default-trigger = "heartbeat";
+       ...
+};
@@ -10,16 +10,10 @@ LED sub-node properties:
 - gpios :  Should specify the LED's GPIO, see "gpios property" in
   Documentation/devicetree/bindings/gpio/gpio.txt.  Active low LEDs should be
   indicated using flags in the GPIO specifier.
-- label :  (optional) The label for this LED.  If omitted, the label is
-  taken from the node name (excluding the unit address).
-- linux,default-trigger :  (optional) This parameter, if present, is a
-  string defining the trigger assigned to the LED.  Current triggers are:
-    "backlight" - LED will act as a back-light, controlled by the framebuffer
-                 system
-    "default-on" - LED will turn on, but see "default-state" below
-    "heartbeat" - LED "double" flashes at a load average based rate
-    "ide-disk" - LED indicates disk activity
-    "timer" - LED flashes at a fixed, configurable rate
+- label :  (optional)
+  see Documentation/devicetree/bindings/leds/common.txt
+- linux,default-trigger :  (optional)
+  see Documentation/devicetree/bindings/leds/common.txt
 - default-state:  (optional) The initial state of the LED.  Valid
   values are "on", "off", and "keep".  If the LED is already on or off
   and the default-state property is set the to same value, then no
index 8e2e0ba..a591c67 100644 (file)
@@ -21,6 +21,12 @@ Optional properties:
 - cd-inverted: when present, polarity on the cd gpio line is inverted
 - wp-inverted: when present, polarity on the wp gpio line is inverted
 - max-frequency: maximum operating clock frequency
+- no-1-8-v: when present, denotes that 1.8v card voltage is not supported on
+  this system, even if the controller claims it is.
+
+Optional SDIO properties:
+- keep-power-in-suspend: Preserves card power during a suspend/resume cycle
+- enable-sdio-wakeup: Enables wake up of host system on SDIO IRQ assertion
 
 Example:
 
@@ -33,4 +39,6 @@ sdhci@ab000000 {
        cd-inverted;
        wp-gpios = <&gpio 70 0>;
        max-frequency = <50000000>;
+       keep-power-in-suspend;
+       enable-sdio-wakeup;
 }
index 630a7d7..97e9e31 100644 (file)
@@ -12,10 +12,6 @@ is used. The Samsung's SDHCI controller bindings extends this as listed below.
 [A] The property "samsung,cd-pinmux-gpio" can be used as stated in the
     "Optional Board Specific Properties" section below.
 
-[B] If core card-detect bindings and "samsung,cd-pinmux-gpio" property
-    is not specified, it is assumed that there is no card detection
-    mechanism used.
-
 Required SoC Specific Properties:
 - compatible: should be one of the following
   - "samsung,s3c6410-sdhci": For controllers compatible with s3c6410 sdhci
@@ -24,14 +20,18 @@ Required SoC Specific Properties:
     controller.
 
 Required Board Specific Properties:
-- gpios: Should specify the gpios used for clock, command and data lines. The
-  gpio specifier format depends on the gpio controller.
+- Samsung GPIO variant (will be completely replaced by pinctrl):
+  - gpios: Should specify the gpios used for clock, command and data lines. The
+    gpio specifier format depends on the gpio controller.
+- Pinctrl variant (preferred if available):
+  - pinctrl-0: Should specify pin control groups used for this controller.
+  - pinctrl-names: Should contain only one value - "default".
 
 Optional Board Specific Properties:
 - samsung,cd-pinmux-gpio: Specifies the card detect line that is routed
   through a pinmux to the card-detect pin of the card slot. This property
   should be used only if none of the mmc core card-detect properties are
-  used.
+  used. Only for Samsung GPIO variant.
 
 Example:
        sdhci@12530000 {
@@ -40,12 +40,18 @@ Example:
                interrupts = <0 75 0>;
                bus-width = <4>;
                cd-gpios = <&gpk2 2 2 3 3>;
+
+               /* Samsung GPIO variant */
                gpios = <&gpk2 0 2 0 3>,  /* clock line */
                        <&gpk2 1 2 0 3>,  /* command line */
                        <&gpk2 3 2 3 3>,  /* data line 0 */
                        <&gpk2 4 2 3 3>,  /* data line 1 */
                        <&gpk2 5 2 3 3>,  /* data line 2 */
                        <&gpk2 6 2 3 3>;  /* data line 3 */
+
+               /* Pinctrl variant */
+               pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4>;
+               pinctrl-names = "default";
        };
 
        Note: This example shows both SoC specific and board specific properties
index be76a23..ed271fc 100644 (file)
@@ -19,6 +19,7 @@ ti,dual-volt: boolean, supports dual voltage cards
 "supply-name" examples are "vmmc", "vmmc_aux" etc
 ti,non-removable: non-removable slot (like eMMC)
 ti,needs-special-reset: Requires a special softreset sequence
+ti,needs-special-hs-handling: HSMMC IP needs special setting for handling High Speed
 
 Example:
        mmc1: mmc@0x4809c000 {
diff --git a/Documentation/devicetree/bindings/mmc/vt8500-sdmmc.txt b/Documentation/devicetree/bindings/mmc/vt8500-sdmmc.txt
new file mode 100644 (file)
index 0000000..d7fb6ab
--- /dev/null
@@ -0,0 +1,23 @@
+* Wondermedia WM8505/WM8650 SD/MMC Host Controller
+
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the wmt-sdmmc driver.
+
+Required properties:
+- compatible: Should be "wm,wm8505-sdhc".
+- interrupts: Two interrupts are required - regular irq and dma irq.
+
+Optional properties:
+- sdon-inverted: SD_ON bit is inverted on the controller
+
+Examples:
+
+sdhc@d800a000 {
+       compatible = "wm,wm8505-sdhc";
+       reg = <0xd800a000 0x1000>;
+       interrupts = <20 21>;
+       clocks = <&sdhc>;
+       bus-width = <4>;
+       sdon-inverted;
+};
+
index bc95495..c79bab0 100644 (file)
@@ -8,9 +8,16 @@ gpios property as described in section VIII.1 in the following order:
 
 MDC, MDIO.
 
+Note: Each gpio-mdio bus should have an alias correctly numbered in "aliases"
+node.
+
 Example:
 
-mdio {
+aliases {
+       mdio-gpio0 = <&mdio0>;
+};
+
+mdio0: mdio {
        compatible = "virtual,mdio-gpio";
        #address-cells = <1>;
        #size-cells = <0>;
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..3a26812
--- /dev/null
@@ -0,0 +1,141 @@
+* 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.
+DEGLITCH       (1 << 2): indicate this pin need deglitch.
+PULL_DOWN      (1 << 3): indicate this pin need a pull down.
+DIS_SCHMIT     (1 << 4): indicate this pin need to disable schmit trigger.
+DEBOUNCE       (1 << 16): indicate this pin need debounce.
+DEBOUNCE_VAL   (0x3fff << 17): debounce val.
+
+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 c8e5782..683fde9 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 c275b70..6f426ed 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,
diff --git a/Documentation/devicetree/bindings/rtc/orion-rtc.txt b/Documentation/devicetree/bindings/rtc/orion-rtc.txt
new file mode 100644 (file)
index 0000000..3bf63ff
--- /dev/null
@@ -0,0 +1,18 @@
+* Mvebu Real Time Clock
+
+RTC controller for the Kirkwood, the Dove, the Armada 370 and the
+Armada XP SoCs
+
+Required properties:
+- compatible : Should be "marvell,orion-rtc"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- interrupts: IRQ line for the RTC.
+
+Example:
+
+rtc@10300 {
+        compatible = "marvell,orion-rtc";
+        reg = <0xd0010300 0x20>;
+        interrupts = <50>;
+};
index 9de2b9f..770a019 100644 (file)
@@ -5,6 +5,7 @@ using them to avoid name-space collisions.
 
 ad     Avionic Design GmbH
 adi    Analog Devices, Inc.
+ak     Asahi Kasei Corp.
 amcc   Applied Micro Circuits Corporation (APM, formally AMCC)
 apm    Applied Micro Circuits Corporation (APM)
 arm    ARM Ltd.
@@ -25,6 +26,7 @@ gef   GE Fanuc Intelligent Platforms Embedded Systems, Inc.
 hp     Hewlett Packard
 ibm    International Business Machines (IBM)
 idt    Integrated Device Technologies, Inc.
+img    Imagination Technologies Ltd.
 intercontrol   Inter Control Group
 linux  Linux-specific binding
 marvell        Marvell Technology Group Ltd.
@@ -34,8 +36,9 @@ national      National Semiconductor
 nintendo       Nintendo
 nvidia NVIDIA
 nxp    NXP Semiconductors
+onnn   ON Semiconductor Corp.
 picochip       Picochip Ltd
-powervr        Imagination Technologies
+powervr        PowerVR (deprecated, use img)
 qcom   Qualcomm, Inc.
 ramtron        Ramtron International
 realtek Realtek Semiconductor Corp.
@@ -45,6 +48,7 @@ schindler     Schindler
 sil    Silicon Image
 simtek
 sirf   SiRF Technology, Inc.
+snps   Synopsys, Inc.
 st     STMicroelectronics
 stericsson     ST-Ericsson
 ti     Texas Instruments
index dca90fe..ef9d06c 100644 (file)
@@ -347,7 +347,7 @@ later), which will happily live at the base of the Linux /sys/devices
 tree.  Therefore, if a DT node is at the root of the tree, then it
 really probably is best registered as a platform_device.
 
-Linux board support code calls of_platform_populate(NULL, NULL, NULL)
+Linux board support code calls of_platform_populate(NULL, NULL, NULL, NULL)
 to kick off discovery of devices at the root of the tree.  The
 parameters are all NULL because when starting from the root of the
 tree, there is no need to provide a starting node (the first NULL), a
index a1793d6..3844d21 100644 (file)
@@ -33,7 +33,7 @@ Table of Contents
   2    Modifying System Parameters
 
   3    Per-Process Parameters
-  3.1  /proc/<pid>/oom_score_adj - Adjust the oom-killer
+  3.1  /proc/<pid>/oom_adj & /proc/<pid>/oom_score_adj - Adjust the oom-killer
                                                                score
   3.2  /proc/<pid>/oom_score - Display current oom-killer score
   3.3  /proc/<pid>/io - Display the IO accounting fields
@@ -1320,10 +1320,10 @@ of the kernel.
 CHAPTER 3: PER-PROCESS PARAMETERS
 ------------------------------------------------------------------------------
 
-3.1 /proc/<pid>/oom_score_adj- Adjust the oom-killer score
+3.1 /proc/<pid>/oom_adj & /proc/<pid>/oom_score_adj- Adjust the oom-killer score
 --------------------------------------------------------------------------------
 
-This file can be used to adjust the badness heuristic used to select which
+These file can be used to adjust the badness heuristic used to select which
 process gets killed in out of memory conditions.
 
 The badness heuristic assigns a value to each candidate task ranging from 0
@@ -1361,6 +1361,12 @@ same system, cpuset, mempolicy, or memory controller resources to use at least
 equivalent to discounting 50% of the task's allowed memory from being considered
 as scoring against the task.
 
+For backwards compatibility with previous kernels, /proc/<pid>/oom_adj may also
+be used to tune the badness score.  Its acceptable values range from -16
+(OOM_ADJUST_MIN) to +15 (OOM_ADJUST_MAX) and a special value of -17
+(OOM_DISABLE) to disable oom killing entirely for that task.  Its value is
+scaled linearly with /proc/<pid>/oom_score_adj.
+
 The value of /proc/<pid>/oom_score_adj may be reduced no lower than the last
 value set by a CAP_SYS_RESOURCE process. To reduce the value any lower
 requires CAP_SYS_RESOURCE.
@@ -1375,7 +1381,9 @@ minimal amount of work.
 -------------------------------------------------------------
 
 This file can be used to check the current score used by the oom-killer is for
-any given <pid>.
+any given <pid>. Use it together with /proc/<pid>/oom_score_adj to tune which
+process should be killed in an out-of-memory situation.
+
 
 3.3  /proc/<pid>/io - Display the IO accounting fields
 -------------------------------------------------------
index 7eceaff..815b711 100644 (file)
  High level behavior (mixed):
  ============================
 
- kernel(driver): calls request_firmware(&fw_entry, $FIRMWARE, device)
-
- userspace:
+ 1), kernel(driver):
+       - calls request_firmware(&fw_entry, $FIRMWARE, device)
+       - kernel searchs the fimware image with name $FIRMWARE directly
+       in the below search path of root filesystem:
+               "/lib/firmware/updates/" UTS_RELEASE,
+               "/lib/firmware/updates",
+               "/lib/firmware/" UTS_RELEASE,
+               "/lib/firmware"
+       - If found, goto 7), else goto 2)
+
+ 2), userspace:
        - /sys/class/firmware/xxx/{loading,data} appear.
        - hotplug gets called with a firmware identifier in $FIRMWARE
          and the usual hotplug environment.
                - hotplug: echo 1 > /sys/class/firmware/xxx/loading
 
- kernel: Discard any previous partial load.
3), kernel: Discard any previous partial load.
 
- userspace:
4), userspace:
                - hotplug: cat appropriate_firmware_image > \
                                        /sys/class/firmware/xxx/data
 
- kernel: grows a buffer in PAGE_SIZE increments to hold the image as it
5), kernel: grows a buffer in PAGE_SIZE increments to hold the image as it
         comes in.
 
- userspace:
6), userspace:
                - hotplug: echo 0 > /sys/class/firmware/xxx/loading
 
- kernel: request_firmware() returns and the driver has the firmware
7), kernel: request_firmware() returns and the driver has the firmware
         image in fw_entry->{data,size}. If something went wrong
         request_firmware() returns non-zero and fw_entry is set to
         NULL.
 
- kernel(driver): Driver code calls release_firmware(fw_entry) releasing
8), kernel(driver): Driver code calls release_firmware(fw_entry) releasing
                 the firmware image and any related resource.
 
  High level behavior (driver code):
index e08a883..77a1d11 100644 (file)
@@ -439,6 +439,48 @@ slower clock delays the rising edge of SCK, and the I2C master adjusts its
 signaling rate accordingly.
 
 
+GPIO controllers and the pinctrl subsystem
+------------------------------------------
+
+A GPIO controller on a SOC might be tightly coupled with the pinctrl
+subsystem, in the sense that the pins can be used by other functions
+together with an optional gpio feature. We have already covered the
+case where e.g. a GPIO controller need to reserve a pin or set the
+direction of a pin by calling any of:
+
+pinctrl_request_gpio()
+pinctrl_free_gpio()
+pinctrl_gpio_direction_input()
+pinctrl_gpio_direction_output()
+
+But how does the pin control subsystem cross-correlate the GPIO
+numbers (which are a global business) to a certain pin on a certain
+pin controller?
+
+This is done by registering "ranges" of pins, which are essentially
+cross-reference tables. These are described in
+Documentation/pinctrl.txt
+
+While the pin allocation is totally managed by the pinctrl subsystem,
+gpio (under gpiolib) is still maintained by gpio drivers. It may happen
+that different pin ranges in a SoC is managed by different gpio drivers.
+
+This makes it logical to let gpio drivers announce their pin ranges to
+the pin ctrl subsystem before it will call 'pinctrl_request_gpio' in order
+to request the corresponding pin to be prepared by the pinctrl subsystem
+before any gpio usage.
+
+For this, the gpio controller can register its pin range with pinctrl
+subsystem. There are two ways of doing it currently: with or without DT.
+
+For with DT support refer to Documentation/devicetree/bindings/gpio/gpio.txt.
+
+For non-DT support, user can call gpiochip_add_pin_range() with appropriate
+parameters to register a range of gpio pins with a pinctrl driver. For this
+exact name string of pinctrl device has to be passed as one of the
+argument to this routine.
+
+
 What do these conventions omit?
 ===============================
 One of the biggest things these conventions omit is pin multiplexing, since
index 2bbebe6..f6e263e 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 c86b50c..3374c08 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 a92918e..8065481 100644 (file)
@@ -10,7 +10,7 @@ Supported chips:
   BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors
     (not yet published)
 
-Author: Andreas Herrmann <andreas.herrmann3@amd.com>
+Author: Andreas Herrmann <herrmann.der.user@googlemail.com>
 
 Description
 -----------
index 790f774..843751c 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 ec9ae67..14c3f4f 100644 (file)
@@ -1175,15 +1175,16 @@ When kbuild executes, the following steps are followed (roughly):
        in an init section in the image. Platform code *must* copy the
        blob to non-init memory prior to calling unflatten_device_tree().
 
-       Example:
-               #arch/x86/platform/ce4100/Makefile
-               clean-files := *dtb.S
+       To use this command, simply add *.dtb into obj-y or targets, or make
+       some other target depend on %.dtb
 
-               DTC_FLAGS := -p 1024
-               obj-y += foo.dtb.o
+       A central rule exists to create $(obj)/%.dtb from $(src)/%.dts;
+       architecture Makefiles do no need to explicitly write out that rule.
 
-               $(obj)/%.dtb: $(src)/%.dts
-                       $(call cmd,dtc)
+       Example:
+               targets += $(dtb-y)
+               clean-files += *.dtb
+               DTC_FLAGS ?= -p 1024
 
 --- 6.8 Custom kbuild commands
 
index 22ae844..0d98fac 100644 (file)
@@ -25,6 +25,8 @@ All attributes are read-only.
        serial                  Product Serial Number (from CID Register)
        erase_size              Erase group size
        preferred_erase_size    Preferred erase size
+       raw_rpmb_size_mult      RPMB partition size
+       rel_sectors             Reliable write sector count
 
 Note on Erase Size and Preferred Erase Size:
 
@@ -65,6 +67,11 @@ Note on Erase Size and Preferred Erase Size:
 
        "preferred_erase_size" is in bytes.
 
+Note on raw_rpmb_size_mult:
+       "raw_rpmb_size_mult" is a mutliple of 128kB block.
+       RPMB size in byte is calculated by using the following equation:
+       RPMB partition size = 128kB x raw_rpmb_size_mult
+
 SD/MMC/SDIO Clock Gating Attribute
 ==================================
 
index 4164f5c..f310ede 100644 (file)
@@ -164,4 +164,4 @@ read the CRC recorded by the NIC on receipt of the packet.
 This requests that the NIC receive all possible frames, including errored
 frames (such as bad FCS, etc).  This can be helpful when sniffing a link with
 bad packets on it.  Some NICs may receive more packets if also put into normal
-PROMISC mdoe.
+PROMISC mode.
index 5b34b76..6d99351 100644 (file)
@@ -32,7 +32,7 @@ no entry is in the forwarding table.
   # ip link delete vxlan0
 
 3. Show vxlan info
-  # ip -d show vxlan0
+  # ip -d link show vxlan0
 
 It is possible to create, destroy and display the vxlan
 forwarding table using the new bridge command.
@@ -41,7 +41,7 @@ forwarding table using the new bridge command.
   # bridge fdb add to 00:17:42:8a:b4:05 dst 192.19.0.2 dev vxlan0
 
 2. Delete forwarding table entry
-  # bridge fdb delete 00:17:42:8a:b4:05
+  # bridge fdb delete 00:17:42:8a:b4:05 dev vxlan0
 
 3. Show forwarding table
   # bridge fdb show dev vxlan0
index 3b4ee53..da40efb 100644 (file)
@@ -364,6 +364,9 @@ will get an pin number into its handled number range. Further it is also passed
 the range ID value, so that the pin controller knows which range it should
 deal with.
 
+Calling pinctrl_add_gpio_range from pinctrl driver is DEPRECATED. Please see
+section 2.1 of Documentation/devicetree/bindings/gpio/gpio.txt on how to bind
+pinctrl and gpio drivers.
 
 PINMUX interfaces
 =================
@@ -1193,4 +1196,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 17e130a..79a2a58 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 642f844..2a4cdda 100644 (file)
@@ -116,6 +116,7 @@ On all -  write a character to /proc/sysrq-trigger.  e.g.:
 'w'    - Dumps tasks that are in uninterruptable (blocked) state.
 
 'x'    - Used by xmon interface on ppc/powerpc platforms.
+          Show global PMU Registers on sparc64.
 
 'y'    - Show global CPU Registers [SPARC-64 specific]
 
diff --git a/Documentation/zh_CN/IRQ.txt b/Documentation/zh_CN/IRQ.txt
new file mode 100644 (file)
index 0000000..956026d
--- /dev/null
@@ -0,0 +1,39 @@
+Chinese translated version of Documentation/IRQ.txt
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly.  However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help.  Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Maintainer: Eric W. Biederman <ebiederman@xmission.com>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/IRQ.txt 的中文翻译
+
+如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
+交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题,请联系中文版维护者。
+英文版维护者: Eric W. Biederman <ebiederman@xmission.com>
+中文版维护者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版校译者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
+
+
+以下为正文
+---------------------------------------------------------------------
+何为 IRQ?
+
+一个 IRQ 是来自某个设备的一个中断请求。目前,它们可以来自一个硬件引脚,
+或来自一个数据包。多个设备可能连接到同个硬件引脚,从而共享一个 IRQ。
+
+一个 IRQ 编号是用于告知硬件中断源的内核标识。通常情况下,这是一个
+全局 irq_desc 数组的索引,但是除了在 linux/interrupt.h 中的实现,
+具体的细节是体系结构特定的。
+
+一个 IRQ 编号是设备上某个可能的中断源的枚举。通常情况下,枚举的编号是
+该引脚在系统内中断控制器的所有输入引脚中的编号。对于 ISA 总线中的情况,
+枚举的是在两个 i8259 中断控制器中 16 个输入引脚。
+
+架构可以对 IRQ 编号指定额外的含义,在硬件涉及任何手工配置的情况下,
+是被提倡的。ISA 的 IRQ 是一个分配这类额外含义的典型例子。
diff --git a/Documentation/zh_CN/arm64/booting.txt b/Documentation/zh_CN/arm64/booting.txt
new file mode 100644 (file)
index 0000000..28fa325
--- /dev/null
@@ -0,0 +1,156 @@
+Chinese translated version of Documentation/arm64/booting.txt
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly.  However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help.  Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Maintainer: Will Deacon <will.deacon@arm.com>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/arm64/booting.txt 的中文翻译
+
+如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
+交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题,请联系中文版维护者。
+
+英文版维护者: Will Deacon <will.deacon@arm.com>
+中文版维护者: 傅炜  Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者: 傅炜  Fu Wei <tekkamanninja@gmail.com>
+中文版校译者: 傅炜  Fu Wei <tekkamanninja@gmail.com>
+
+以下为正文
+---------------------------------------------------------------------
+                       启动 AArch64 Linux
+                       ==================
+
+作者: Will Deacon <will.deacon@arm.com>
+日期: 2012 年 09 月 07 日
+
+本文档基于 Russell King 的 ARM 启动文档,且适用于所有公开发布的
+AArch64 Linux 内核代码。
+
+AArch64 异常模型由多个异常级别(EL0 - EL3)组成,对于 EL0 和 EL1
+异常级有对应的安全和非安全模式。EL2 是系统管理级,且仅存在于
+非安全模式下。EL3 是最高特权级,且仅存在于安全模式下。
+
+基于本文档的目的,我们将简单地使用‘引导装载程序’(‘boot loader’)
+这个术语来定义在将控制权交给 Linux 内核前 CPU 上执行的所有软件。
+这可能包含安全监控和系统管理代码,或者它可能只是一些用于准备最小启动
+环境的指令。
+
+基本上,引导装载程序(至少)应实现以下操作:
+
+1、设置和初始化 RAM
+2、设置设备树数据
+3、解压内核映像
+4、调用内核映像
+
+
+1、设置和初始化 RAM
+-----------------
+
+必要性: 强制
+
+引导装载程序应该找到并初始化系统中所有内核用于保持系统变量数据的 RAM。
+这个操作的执行是设备依赖的。(它可能使用内部算法来自动定位和计算所有
+RAM,或可能使用对这个设备已知的 RAM 信息,还可能使用任何引导装载程序
+设计者想到的匹配方法。)
+
+
+2、设置设备树数据
+---------------
+
+必要性: 强制
+
+设备树数据块(dtb)大小必须不大于 2 MB,且位于从内核映像起始算起第一个
+512MB 内的 2MB 边界上。这使得内核可以通过初始页表中的单个节描述符来
+映射此数据块。
+
+
+3、解压内核映像
+-------------
+
+必要性: 可选
+
+AArch64 内核当前没有提供自解压代码,因此如果使用了压缩内核映像文件
+(比如 Image.gz),则需要通过引导装载程序(使用 gzip 等)来进行解压。
+若引导装载程序没有实现这个需求,就要使用非压缩内核映像文件。
+
+
+4、调用内核映像
+-------------
+
+必要性: 强制
+
+已解压的内核映像包含一个 32 字节的头,内容如下:
+
+  u32 magic    = 0x14000008;   /* 跳转到 stext, 小端 */
+  u32 res0     = 0;            /* 保留 */
+  u64 text_offset;             /* 映像装载偏移 */
+  u64 res1     = 0;            /* 保留 */
+  u64 res2     = 0;            /* 保留 */
+
+映像必须位于系统 RAM 起始处的特定偏移(当前是 0x80000)。系统 RAM
+的起始地址必须是以 2MB 对齐的。
+
+在跳转入内核前,必须符合以下状态:
+
+- 停止所有 DMA 设备,这样内存数据就不会因为虚假网络包或磁盘数据而
+  被破坏。这可能可以节省你许多的调试时间。
+
+- 主 CPU 通用寄存器设置
+  x0 = 系统 RAM 中设备树数据块(dtb)的物理地址。
+  x1 = 0 (保留,将来可能使用)
+  x2 = 0 (保留,将来可能使用)
+  x3 = 0 (保留,将来可能使用)
+
+- CPU 模式
+  所有形式的中断必须在 PSTATE.DAIF 中被屏蔽(Debug、SError、IRQ
+  和 FIQ)。
+  CPU 必须处于 EL2(推荐,可访问虚拟化扩展)或非安全 EL1 模式下。
+
+- 高速缓存、MMU
+  MMU 必须关闭。
+  指令缓存开启或关闭都可以。
+  数据缓存必须关闭且无效。
+  外部高速缓存(如果存在)必须配置并禁用。
+
+- 架构计时器
+  CNTFRQ 必须设定为计时器的频率。
+  如果在 EL1 模式下进入内核,则 CNTHCTL_EL2 中的 EL1PCTEN (bit 0)
+  必须置位。
+
+- 一致性
+  通过内核启动的所有 CPU 在内核入口地址上必须处于相同的一致性域中。
+  这可能要根据具体实现来定义初始化过程,以使能每个CPU上对维护操作的
+  接收。
+
+- 系统寄存器
+  在进入内核映像的异常级中,所有构架中可写的系统寄存器必须通过软件
+  在一个更高的异常级别下初始化,以防止在 未知 状态下运行。
+
+引导装载程序必须在每个 CPU 处于以下状态时跳入内核入口:
+
+- 主 CPU 必须直接跳入内核映像的第一条指令。通过此 CPU 传递的设备树
+  数据块必须在每个 CPU 节点中包含以下内容:
+
+    1、‘enable-method’属性。目前,此字段支持的值仅为字符串“spin-table”。
+
+    2、‘cpu-release-addr’标识一个 64-bit、初始化为零的内存位置。
+
+  引导装载程序必须生成这些设备树属性,并在跳入内核入口之前将其插入
+  数据块。
+
+- 任何辅助 CPU 必须在内存保留区(通过设备树中的 /memreserve/ 域传递
+  给内核)中自旋于内核之外,轮询它们的 cpu-release-addr 位置(必须
+  包含在保留区中)。可通过插入 wfe 指令来降低忙循环开销,而主 CPU 将
+  发出 sev 指令。当对 cpu-release-addr 所指位置的读取操作返回非零值
+  时,CPU 必须直接跳入此值所指向的地址。
+
+- 辅助 CPU 通用寄存器设置
+  x0 = 0 (保留,将来可能使用)
+  x1 = 0 (保留,将来可能使用)
+  x2 = 0 (保留,将来可能使用)
+  x3 = 0 (保留,将来可能使用)
diff --git a/Documentation/zh_CN/arm64/memory.txt b/Documentation/zh_CN/arm64/memory.txt
new file mode 100644 (file)
index 0000000..83b5193
--- /dev/null
@@ -0,0 +1,93 @@
+Chinese translated version of Documentation/arm64/memory.txt
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly.  However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help.  Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Maintainer: Catalin Marinas <catalin.marinas@arm.com>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/arm64/memory.txt 的中文翻译
+
+如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
+交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题,请联系中文版维护者。
+
+英文版维护者: Catalin Marinas <catalin.marinas@arm.com>
+中文版维护者: 傅炜  Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者: 傅炜  Fu Wei <tekkamanninja@gmail.com>
+中文版校译者: 傅炜  Fu Wei <tekkamanninja@gmail.com>
+
+以下为正文
+---------------------------------------------------------------------
+                    Linux 在 AArch64 中的内存布局
+                    ===========================
+
+作者: Catalin Marinas <catalin.marinas@arm.com>
+日期: 2012 年 02 月 20 日
+
+本文档描述 AArch64 Linux 内核所使用的虚拟内存布局。此构架可以实现
+页大小为 4KB 的 4 级转换表和页大小为 64KB 的 3 级转换表。
+
+AArch64 Linux 使用页大小为 4KB 的 3 级转换表配置,对于用户和内核
+都有 39-bit (512GB) 的虚拟地址空间。对于页大小为 64KB的配置,仅
+使用 2 级转换表,但内存布局相同。
+
+用户地址空间的 63:39 位为 0,而内核地址空间的相应位为 1。TTBRx 的
+选择由虚拟地址的 63 位给出。swapper_pg_dir 仅包含内核(全局)映射,
+而用户 pgd 仅包含用户(非全局)映射。swapper_pgd_dir 地址被写入
+TTBR1 中,且从不写入 TTBR0。
+
+
+AArch64 Linux 内存布局:
+
+起始地址                   结束地址                    大小          用途
+-----------------------------------------------------------------------
+0000000000000000       0000007fffffffff         512GB          用户空间
+
+ffffff8000000000       ffffffbbfffcffff        ~240GB          vmalloc
+
+ffffffbbfffd0000       ffffffbcfffdffff          64KB          [防护页]
+
+ffffffbbfffe0000       ffffffbcfffeffff          64KB          PCI I/O 空间
+
+ffffffbbffff0000       ffffffbcffffffff          64KB          [防护页]
+
+ffffffbc00000000       ffffffbdffffffff           8GB          vmemmap
+
+ffffffbe00000000       ffffffbffbffffff          ~8GB          [防护页,未来用于 vmmemap]
+
+ffffffbffc000000       ffffffbfffffffff          64MB          模块
+
+ffffffc000000000       ffffffffffffffff         256GB          内存空间
+
+
+4KB 页大小的转换表查找:
+
++--------+--------+--------+--------+--------+--------+--------+--------+
+|63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0|
++--------+--------+--------+--------+--------+--------+--------+--------+
+ |                 |         |         |         |         |
+ |                 |         |         |         |         v
+ |                 |         |         |         |   [11:0]  页内偏移
+ |                 |         |         |         +-> [20:12] L3 索引
+ |                 |         |         +-----------> [29:21] L2 索引
+ |                 |         +---------------------> [38:30] L1 索引
+ |                 +-------------------------------> [47:39] L0 索引 (未使用)
+ +-------------------------------------------------> [63] TTBR0/1
+
+
+64KB 页大小的转换表查找:
+
++--------+--------+--------+--------+--------+--------+--------+--------+
+|63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0|
++--------+--------+--------+--------+--------+--------+--------+--------+
+ |                 |    |               |              |
+ |                 |    |               |              v
+ |                 |    |               |            [15:0]  页内偏移
+ |                 |    |               +----------> [28:16] L3 索引
+ |                 |    +--------------------------> [41:29] L2 索引 (仅使用 38:29 )
+ |                 +-------------------------------> [47:42] L1 索引 (未使用)
+ +-------------------------------------------------> [63] TTBR0/1
index e73060f..cf7ff78 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/
@@ -502,7 +503,7 @@ F:  include/linux/altera_uart.h
 F:     include/linux/altera_jtaguart.h
 
 AMD FAM15H PROCESSOR POWER MONITORING DRIVER
-M:     Andreas Herrmann <andreas.herrmann3@amd.com>
+M:     Andreas Herrmann <herrmann.der.user@googlemail.com>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     Documentation/hwmon/fam15h_power
@@ -525,17 +526,17 @@ F:        drivers/video/geode/
 F:     arch/x86/include/asm/geode.h
 
 AMD IOMMU (AMD-VI)
-M:     Joerg Roedel <joerg.roedel@amd.com>
+M:     Joerg Roedel <joro@8bytes.org>
 L:     iommu@lists.linux-foundation.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git
-S:     Supported
+S:     Maintained
 F:     drivers/iommu/amd_iommu*.[ch]
 F:     include/linux/amd-iommu.h
 
 AMD MICROCODE UPDATE SUPPORT
-M:     Andreas Herrmann <andreas.herrmann3@amd.com>
+M:     Andreas Herrmann <herrmann.der.user@googlemail.com>
 L:     amd64-microcode@amd64.org
-S:     Supported
+S:     Maintained
 F:     arch/x86/kernel/microcode_amd.c
 
 AMS (Apple Motion Sensor) DRIVER
@@ -636,6 +637,13 @@ W: http://www.arm.linux.org.uk/
 S:     Maintained
 F:     arch/arm/
 
+ARM SUB-ARCHITECTURES
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     MAINTAINED
+F:     arch/arm/mach-*/
+F:     arch/arm/plat-*/
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git
+
 ARM PRIMECELL AACI PL041 DRIVER
 M:     Russell King <linux@arm.linux.org.uk>
 S:     Maintained
@@ -833,6 +841,14 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git
 F:     arch/arm/mach-sa1100/jornada720.c
 F:     arch/arm/mach-sa1100/include/mach/jornada720.h
 
+ARM/IGEP MACHINE SUPPORT
+M:     Enric Balletbo i Serra <eballetbo@gmail.com>
+M:     Javier Martinez Canillas <javier@dowhile0.org>
+L:     linux-omap@vger.kernel.org
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+F:     arch/arm/mach-omap2/board-igep0020.c
+
 ARM/INCOME PXA270 SUPPORT
 M:     Marek Vasut <marek.vasut@gmail.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1221,6 +1237,7 @@ F:        drivers/video/wm8505fb*
 F:     drivers/video/wmt_ge_rops.*
 F:     drivers/tty/serial/vt8500_serial.c
 F:     drivers/rtc/rtc-vt8500-c
+F:     drivers/mmc/host/wmt-sdmmc.c
 
 ARM/ZIPIT Z2 SUPPORT
 M:     Marek Vasut <marek.vasut@gmail.com>
@@ -1352,14 +1369,6 @@ S:       Maintained
 F:     drivers/atm/
 F:     include/linux/atm*
 
-ATMEL AT91 MCI DRIVER
-M:     Ludovic Desroches <ludovic.desroches@atmel.com>
-L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-W:     http://www.atmel.com/products/AT91/
-W:     http://www.at91.com/
-S:     Maintained
-F:     drivers/mmc/host/at91_mci.c
-
 ATMEL AT91 / AT32 MCI DRIVER
 M:     Ludovic Desroches <ludovic.desroches@atmel.com>
 S:     Maintained
@@ -1978,7 +1987,6 @@ F:        fs/coda/
 F:     include/linux/coda*.h
 
 COMMON CLK FRAMEWORK
-M:     Mike Turquette <mturquette@ti.com>
 M:     Mike Turquette <mturquette@linaro.org>
 L:     linux-arm-kernel@lists.infradead.org (same as CLK API & CLKDEV)
 T:     git git://git.linaro.org/people/mturquette/linux.git
@@ -2499,6 +2507,7 @@ M:        Joonyoung Shim <jy0922.shim@samsung.com>
 M:     Seung-Woo Kim <sw0312.kim@samsung.com>
 M:     Kyungmin Park <kyungmin.park@samsung.com>
 L:     dri-devel@lists.freedesktop.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git
 S:     Supported
 F:     drivers/gpu/drm/exynos
 F:     include/drm/exynos*
@@ -2699,10 +2708,10 @@ F:      include/linux/edac.h
 
 EDAC-AMD64
 M:     Doug Thompson <dougthompson@xmission.com>
-M:     Borislav Petkov <borislav.petkov@amd.com>
+M:     Borislav Petkov <bp@alien8.de>
 L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
-S:     Supported
+S:     Maintained
 F:     drivers/edac/amd64_edac*
 
 EDAC-E752X
@@ -2801,6 +2810,7 @@ F:        sound/usb/misc/ua101.c
 EXTENSIBLE FIRMWARE INTERFACE (EFI)
 M:     Matt Fleming <matt.fleming@intel.com>
 L:     linux-efi@vger.kernel.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git
 S:     Maintained
 F:     Documentation/x86/efi-stub.txt
 F:     arch/ia64/kernel/efi.c
@@ -3588,6 +3598,49 @@ F:       drivers/hid/hid-hyperv.c
 F:     drivers/net/hyperv/
 F:     drivers/staging/hv/
 
+I2C OVER PARALLEL PORT
+M:     Jean Delvare <khali@linux-fr.org>
+L:     linux-i2c@vger.kernel.org
+S:     Maintained
+F:     Documentation/i2c/busses/i2c-parport
+F:     Documentation/i2c/busses/i2c-parport-light
+F:     drivers/i2c/busses/i2c-parport.c
+F:     drivers/i2c/busses/i2c-parport-light.c
+
+I2C/SMBUS CONTROLLER DRIVERS FOR PC
+M:     Jean Delvare <khali@linux-fr.org>
+L:     linux-i2c@vger.kernel.org
+S:     Maintained
+F:     Documentation/i2c/busses/i2c-ali1535
+F:     Documentation/i2c/busses/i2c-ali1563
+F:     Documentation/i2c/busses/i2c-ali15x3
+F:     Documentation/i2c/busses/i2c-amd756
+F:     Documentation/i2c/busses/i2c-amd8111
+F:     Documentation/i2c/busses/i2c-i801
+F:     Documentation/i2c/busses/i2c-nforce2
+F:     Documentation/i2c/busses/i2c-piix4
+F:     Documentation/i2c/busses/i2c-sis5595
+F:     Documentation/i2c/busses/i2c-sis630
+F:     Documentation/i2c/busses/i2c-sis96x
+F:     Documentation/i2c/busses/i2c-via
+F:     Documentation/i2c/busses/i2c-viapro
+F:     drivers/i2c/busses/i2c-ali1535.c
+F:     drivers/i2c/busses/i2c-ali1563.c
+F:     drivers/i2c/busses/i2c-ali15x3.c
+F:     drivers/i2c/busses/i2c-amd756.c
+F:     drivers/i2c/busses/i2c-amd756-s4882.c
+F:     drivers/i2c/busses/i2c-amd8111.c
+F:     drivers/i2c/busses/i2c-i801.c
+F:     drivers/i2c/busses/i2c-isch.c
+F:     drivers/i2c/busses/i2c-nforce2.c
+F:     drivers/i2c/busses/i2c-nforce2-s4985.c
+F:     drivers/i2c/busses/i2c-piix4.c
+F:     drivers/i2c/busses/i2c-sis5595.c
+F:     drivers/i2c/busses/i2c-sis630.c
+F:     drivers/i2c/busses/i2c-sis96x.c
+F:     drivers/i2c/busses/i2c-via.c
+F:     drivers/i2c/busses/i2c-viapro.c
+
 I2C/SMBUS STUB DRIVER
 M:     "Mark M. Hoffman" <mhoffman@lightlink.com>
 L:     linux-i2c@vger.kernel.org
@@ -3595,9 +3648,8 @@ S:        Maintained
 F:     drivers/i2c/busses/i2c-stub.c
 
 I2C SUBSYSTEM
-M:     "Jean Delvare (PC drivers, core)" <khali@linux-fr.org>
+M:     Wolfram Sang <w.sang@pengutronix.de>
 M:     "Ben Dooks (embedded platforms)" <ben-linux@fluff.org>
-M:     "Wolfram Sang (embedded platforms)" <w.sang@pengutronix.de>
 L:     linux-i2c@vger.kernel.org
 W:     http://i2c.wiki.kernel.org/
 T:     quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-i2c/
@@ -3608,6 +3660,13 @@ F:       drivers/i2c/
 F:     include/linux/i2c.h
 F:     include/linux/i2c-*.h
 
+I2C-TAOS-EVM DRIVER
+M:     Jean Delvare <khali@linux-fr.org>
+L:     linux-i2c@vger.kernel.org
+S:     Maintained
+F:     Documentation/i2c/busses/i2c-taos-evm
+F:     drivers/i2c/busses/i2c-taos-evm.c
+
 I2C-TINY-USB DRIVER
 M:     Till Harbaum <till@harbaum.org>
 L:     linux-i2c@vger.kernel.org
@@ -3694,7 +3753,7 @@ S:        Maintained
 F:     drivers/platform/x86/ideapad-laptop.c
 
 IDE/ATAPI DRIVERS
-M:     Borislav Petkov <petkovbb@gmail.com>
+M:     Borislav Petkov <bp@alien8.de>
 L:     linux-ide@vger.kernel.org
 S:     Maintained
 F:     Documentation/cdrom/ide-cd
@@ -4221,8 +4280,8 @@ F:        include/linux/lockd/
 F:     include/linux/sunrpc/
 
 KERNEL VIRTUAL MACHINE (KVM)
-M:     Avi Kivity <avi@redhat.com>
 M:     Marcelo Tosatti <mtosatti@redhat.com>
+M:     Gleb Natapov <gleb@redhat.com>
 L:     kvm@vger.kernel.org
 W:     http://kvm.qumranet.com
 S:     Supported
@@ -4372,7 +4431,7 @@ F:        Documentation/scsi/53c700.txt
 F:     drivers/scsi/53c700*
 
 LED SUBSYSTEM
-M:     Bryan Wu <bryan.wu@canonical.com>
+M:     Bryan Wu <cooloney@gmail.com>
 M:     Richard Purdie <rpurdie@rpsys.net>
 L:     linux-leds@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds.git
@@ -5019,6 +5078,20 @@ F:       net/ipv6/
 F:     include/net/ip*
 F:     arch/x86/net/*
 
+NETWORKING [IPSEC]
+M:     Steffen Klassert <steffen.klassert@secunet.com>
+M:     Herbert Xu <herbert@gondor.apana.org.au>
+M:     "David S. Miller" <davem@davemloft.net>
+L:     netdev@vger.kernel.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
+S:     Maintained
+F:     net/xfrm/
+F:     net/key/
+F:     net/ipv4/xfrm*
+F:     net/ipv6/xfrm*
+F:     include/uapi/linux/xfrm.h
+F:     include/net/xfrm.h
+
 NETWORKING [LABELED] (NetLabel, CIPSO, Labeled IPsec, SECMARK)
 M:     Paul Moore <paul@paul-moore.com>
 L:     netdev@vger.kernel.org
@@ -5046,7 +5119,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>
@@ -5334,7 +5413,7 @@ S:        Maintained
 F:     sound/drivers/opl4/
 
 OPROFILE
-M:     Robert Richter <robert.richter@amd.com>
+M:     Robert Richter <rric@kernel.org>
 L:     oprofile-list@lists.sf.net
 S:     Maintained
 F:     arch/*/include/asm/oprofile*.h
@@ -5609,6 +5688,12 @@ S:       Maintained
 F:     drivers/pinctrl/
 F:     include/linux/pinctrl/
 
+PIN CONTROLLER - ATMEL AT91
+M:     Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+F:     drivers/pinctrl/pinctrl-at91.c
+
 PIN CONTROLLER - ST SPEAR
 M:     Viresh Kumar <viresh.linux@gmail.com>
 L:     spear-devel@list.st.com
@@ -5618,7 +5703,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
@@ -7180,6 +7265,14 @@ L:       linux-xtensa@linux-xtensa.org
 S:     Maintained
 F:     arch/xtensa/
 
+THERMAL
+M:      Zhang Rui <rui.zhang@intel.com>
+L:      linux-pm@vger.kernel.org
+T:      git git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git
+S:      Supported
+F:      drivers/thermal/
+F:      include/linux/thermal.h
+
 THINKPAD ACPI EXTRAS DRIVER
 M:     Henrique de Moraes Holschuh <ibm-acpi@hmh.eng.br>
 L:     ibm-acpi-devel@lists.sourceforge.net
@@ -7731,6 +7824,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
@@ -7850,13 +7950,6 @@ M:       Roger Luethi <rl@hellgate.ch>
 S:     Maintained
 F:     drivers/net/ethernet/via/via-rhine.c
 
-VIAPRO SMBUS DRIVER
-M:     Jean Delvare <khali@linux-fr.org>
-L:     linux-i2c@vger.kernel.org
-S:     Maintained
-F:     Documentation/i2c/busses/i2c-viapro
-F:     drivers/i2c/busses/i2c-viapro.c
-
 VIA SD/MMC CARD CONTROLLER DRIVER
 M:     Bruce Chang <brucechang@via.com.tw>
 M:     Harald Welte <HaraldWelte@viatech.com>
@@ -8111,7 +8204,7 @@ F:        drivers/platform/x86
 
 X86 MCE INFRASTRUCTURE
 M:     Tony Luck <tony.luck@intel.com>
-M:     Borislav Petkov <bp@amd64.org>
+M:     Borislav Petkov <bp@alien8.de>
 L:     linux-edac@vger.kernel.org
 S:     Maintained
 F:     arch/x86/kernel/cpu/mcheck/*
index 5be2ee8..540f7b2 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 7
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION =
 NAME = Terrified Chipmunk
 
 # *DOCUMENTATION*
@@ -437,7 +437,9 @@ endif
 PHONY += asm-generic
 asm-generic:
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.asm-generic \
-                   obj=arch/$(SRCARCH)/include/generated/asm
+                   src=asm obj=arch/$(SRCARCH)/include/generated/asm
+       $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.asm-generic \
+                   src=uapi/asm obj=arch/$(SRCARCH)/include/generated/uapi/asm
 
 # To make sure we do not include .config for any of the *config targets
 # catch them early, and hand them over to scripts/kconfig/Makefile
@@ -717,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/
 
@@ -1308,10 +1321,12 @@ kernelversion:
 
 # Clear a bunch of variables before executing the submake
 tools/: FORCE
-       $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= -C $(src)/tools/
+       $(Q)mkdir -p $(objtree)/tools
+       $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= O=$(objtree) subdir=tools -C $(src)/tools/
 
 tools/%: FORCE
-       $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= -C $(src)/tools/ $*
+       $(Q)mkdir -p $(objtree)/tools
+       $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= O=$(objtree) subdir=tools -C $(src)/tools/ $*
 
 # Single targets
 # ---------------------------------------------------------------------------
index 4554ecb..1f8c729 100644 (file)
@@ -7,6 +7,7 @@
 #include <asm/processor.h>
 #include <asm/types.h>
 #include <asm/hwrpb.h>
+#include <asm/sysinfo.h>
 #endif
 
 #ifndef __ASSEMBLY__
@@ -21,6 +22,7 @@ struct thread_info {
        mm_segment_t            addr_limit;     /* thread address space */
        unsigned                cpu;            /* current CPU */
        int                     preempt_count; /* 0 => preemptable, <0 => BUG */
+       unsigned int            status;         /* thread-synchronous flags */
 
        int bpt_nsaved;
        unsigned long bpt_addr[2];              /* breakpoint handling  */
@@ -63,8 +65,6 @@ register struct thread_info *__current_thread_info __asm__("$8");
  * - these are process state flags and used from assembly
  * - pending work-to-be-done flags come first and must be assigned to be
  *   within bits 0 to 7 to fit in and immediate operand.
- * - ALPHA_UAC_SHIFT below must be kept consistent with the unaligned
- *   control flags.
  *
  * TIF_SYSCALL_TRACE is known to be 0 via blbs.
  */
@@ -72,18 +72,12 @@ register struct thread_info *__current_thread_info __asm__("$8");
 #define TIF_NOTIFY_RESUME      1       /* callback before returning to user */
 #define TIF_SIGPENDING         2       /* signal pending */
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
-#define TIF_POLLING_NRFLAG     8       /* poll_idle is polling NEED_RESCHED */
 #define TIF_DIE_IF_KERNEL      9       /* dik recursion lock */
-#define TIF_UAC_NOPRINT                10      /* ! Preserve sequence of following */
-#define TIF_UAC_NOFIX          11      /* ! flags as they match            */
-#define TIF_UAC_SIGBUS         12      /* ! userspace part of 'osf_sysinfo' */
 #define TIF_MEMDIE             13      /* is terminating due to OOM killer */
-#define TIF_RESTORE_SIGMASK    14      /* restore signal mask in do_signal */
 
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
-#define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
 
 /* Work to do on interrupt/exception return.  */
@@ -94,29 +88,63 @@ register struct thread_info *__current_thread_info __asm__("$8");
 #define _TIF_ALLWORK_MASK      (_TIF_WORK_MASK         \
                                 | _TIF_SYSCALL_TRACE)
 
-#define ALPHA_UAC_SHIFT                TIF_UAC_NOPRINT
-#define ALPHA_UAC_MASK         (1 << TIF_UAC_NOPRINT | 1 << TIF_UAC_NOFIX | \
-                                1 << TIF_UAC_SIGBUS)
+#define TS_UAC_NOPRINT         0x0001  /* ! Preserve the following three */
+#define TS_UAC_NOFIX           0x0002  /* ! flags as they match          */
+#define TS_UAC_SIGBUS          0x0004  /* ! userspace part of 'osf_sysinfo' */
+#define TS_RESTORE_SIGMASK     0x0008  /* restore signal mask in do_signal() */
+#define TS_POLLING             0x0010  /* idle task polling need_resched,
+                                          skip sending interrupt */
 
-#define SET_UNALIGN_CTL(task,value)    ({                                   \
-       task_thread_info(task)->flags = ((task_thread_info(task)->flags &    \
-               ~ALPHA_UAC_MASK)                                             \
-               | (((value) << ALPHA_UAC_SHIFT)       & (1<<TIF_UAC_NOPRINT))\
-               | (((value) << (ALPHA_UAC_SHIFT + 1)) & (1<<TIF_UAC_SIGBUS)) \
-               | (((value) << (ALPHA_UAC_SHIFT - 1)) & (1<<TIF_UAC_NOFIX)));\
+#define tsk_is_polling(t) (task_thread_info(t)->status & TS_POLLING)
+
+#ifndef __ASSEMBLY__
+#define HAVE_SET_RESTORE_SIGMASK       1
+static inline void set_restore_sigmask(void)
+{
+       struct thread_info *ti = current_thread_info();
+       ti->status |= TS_RESTORE_SIGMASK;
+       WARN_ON(!test_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags));
+}
+static inline void clear_restore_sigmask(void)
+{
+       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
+}
+static inline bool test_restore_sigmask(void)
+{
+       return current_thread_info()->status & TS_RESTORE_SIGMASK;
+}
+static inline bool test_and_clear_restore_sigmask(void)
+{
+       struct thread_info *ti = current_thread_info();
+       if (!(ti->status & TS_RESTORE_SIGMASK))
+               return false;
+       ti->status &= ~TS_RESTORE_SIGMASK;
+       return true;
+}
+#endif
+
+#define SET_UNALIGN_CTL(task,value)    ({                              \
+       __u32 status = task_thread_info(task)->status & ~UAC_BITMASK;   \
+       if (value & PR_UNALIGN_NOPRINT)                                 \
+               status |= TS_UAC_NOPRINT;                               \
+       if (value & PR_UNALIGN_SIGBUS)                                  \
+               status |= TS_UAC_SIGBUS;                                \
+       if (value & 4)  /* alpha-specific */                            \
+               status |= TS_UAC_NOFIX;                                 \
+       task_thread_info(task)->status = status;                        \
        0; })
 
 #define GET_UNALIGN_CTL(task,value)    ({                              \
-       put_user((task_thread_info(task)->flags & (1 << TIF_UAC_NOPRINT))\
-                 >> ALPHA_UAC_SHIFT                                    \
-                | (task_thread_info(task)->flags & (1 << TIF_UAC_SIGBUS))\
-                >> (ALPHA_UAC_SHIFT + 1)                               \
-                | (task_thread_info(task)->flags & (1 << TIF_UAC_NOFIX))\
-                >> (ALPHA_UAC_SHIFT - 1),                              \
-                (int __user *)(value));                                \
+       __u32 status = task_thread_info(task)->status & ~UAC_BITMASK;   \
+       __u32 res = 0;                                                  \
+       if (status & TS_UAC_NOPRINT)                                    \
+               res |= PR_UNALIGN_NOPRINT;                              \
+       if (status & TS_UAC_SIGBUS)                                     \
+               res |= PR_UNALIGN_SIGBUS;                               \
+       if (status & TS_UAC_NOFIX)                                      \
+               res |= 4;                                               \
+       put_user(res, (int __user *)(value));                           \
        })
 
-#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
-
 #endif /* __KERNEL__ */
 #endif /* _ALPHA_THREAD_INFO_H */
index 9eb0905..14db93e 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;
 
@@ -793,8 +793,7 @@ SYSCALL_DEFINE5(osf_getsysinfo, unsigned long, op, void __user *, buffer,
        case GSI_UACPROC:
                if (nbytes < sizeof(unsigned int))
                        return -EINVAL;
-               w = (current_thread_info()->flags >> ALPHA_UAC_SHIFT) &
-                       UAC_BITMASK;
+               w = current_thread_info()->status & UAC_BITMASK;
                if (put_user(w, (unsigned int __user *)buffer))
                        return -EFAULT;
                return 1;
@@ -904,24 +903,20 @@ SYSCALL_DEFINE5(osf_setsysinfo, unsigned long, op, void __user *, buffer,
                break;
 
        case SSI_NVPAIRS: {
-               unsigned long v, w, i;
-               unsigned int old, new;
+               unsigned __user *p = buffer;
+               unsigned i;
                
-               for (i = 0; i < nbytes; ++i) {
+               for (i = 0, p = buffer; i < nbytes; ++i, p += 2) {
+                       unsigned v, w, status;
 
-                       if (get_user(v, 2*i + (unsigned int __user *)buffer))
-                               return -EFAULT;
-                       if (get_user(w, 2*i + 1 + (unsigned int __user *)buffer))
+                       if (get_user(v, p) || get_user(w, p + 1))
                                return -EFAULT;
                        switch (v) {
                        case SSIN_UACPROC:
-                       again:
-                               old = current_thread_info()->flags;
-                               new = old & ~(UAC_BITMASK << ALPHA_UAC_SHIFT);
-                               new = new | (w & UAC_BITMASK) << ALPHA_UAC_SHIFT;
-                               if (cmpxchg(&current_thread_info()->flags,
-                                           old, new) != old)
-                                       goto again;
+                               w &= UAC_BITMASK;
+                               status = current_thread_info()->status;
+                               status = (status & ~UAC_BITMASK) | w;
+                               current_thread_info()->status = status;
                                break;
  
                        default:
index 4054e0f..51987dc 100644 (file)
@@ -49,7 +49,7 @@ EXPORT_SYMBOL(pm_power_off);
 void
 cpu_idle(void)
 {
-       set_thread_flag(TIF_POLLING_NRFLAG);
+       current_thread_info()->status |= TS_POLLING;
 
        while (1) {
                /* FIXME -- EV6 and LCA45 know how to power down
index 80d987c..272666d 100644 (file)
@@ -780,17 +780,17 @@ do_entUnaUser(void __user * va, unsigned long opcode,
        /* Check the UAC bits to decide what the user wants us to do
           with the unaliged access.  */
 
-       if (!test_thread_flag (TIF_UAC_NOPRINT)) {
+       if (!(current_thread_info()->status & TS_UAC_NOPRINT)) {
                if (__ratelimit(&ratelimit)) {
                        printk("%s(%d): unaligned trap at %016lx: %p %lx %ld\n",
                               current->comm, task_pid_nr(current),
                               regs->pc - 4, va, opcode, reg);
                }
        }
-       if (test_thread_flag (TIF_UAC_SIGBUS))
+       if ((current_thread_info()->status & TS_UAC_SIGBUS))
                goto give_sigbus;
        /* Not sure why you'd want to use this, but... */
-       if (test_thread_flag (TIF_UAC_NOFIX))
+       if ((current_thread_info()->status & TS_UAC_NOFIX))
                return;
 
        /* Don't bother reading ds in the access check since we already
index f456cf4..8a027f9 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.
@@ -548,6 +550,7 @@ config ARCH_KIRKWOOD
        select CPU_FEROCEON
        select GENERIC_CLOCKEVENTS
        select PCI
+       select PCI_QUIRKS
        select PLAT_ORION_LEGACY
        help
          Support for the following Marvell Kirkwood series SoCs:
@@ -587,6 +590,7 @@ config ARCH_MMP
        select GPIO_PXA
        select IRQ_DOMAIN
        select NEED_MACH_GPIO_H
+       select PINCTRL
        select PLAT_PXA
        select SPARSE_IRQ
        help
@@ -905,6 +909,7 @@ config ARCH_NOMADIK
 
 config PLAT_SPEAR
        bool "ST SPEAr"
+       select ARCH_HAS_CPUFREQ
        select ARCH_REQUIRE_GPIOLIB
        select ARM_AMBA
        select CLKDEV_LOOKUP
@@ -1604,8 +1609,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.
@@ -1646,8 +1651,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
@@ -1851,6 +1856,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 f023e3a..c35baf1 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__
 
@@ -291,10 +292,10 @@ zinstall uinstall install: vmlinux
        $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
 
 %.dtb: scripts
-       $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
+       $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@
 
 dtbs: scripts
-       $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
+       $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) dtbs
 
 # We use MRPROPER_FILES and CLEAN_FILES now
 archclean:
index 3fdab01..abfce28 100644 (file)
@@ -15,8 +15,6 @@ ifneq ($(MACHINE),)
 include $(srctree)/$(MACHINE)/Makefile.boot
 endif
 
-include $(srctree)/arch/arm/boot/dts/Makefile
-
 # Note: the following conditions must always be true:
 #   ZRELADDR == virt_to_phys(PAGE_OFFSET + TEXT_OFFSET)
 #   PARAMS_PHYS must be within 4MB of ZRELADDR
@@ -33,7 +31,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,27 +46,17 @@ $(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
 
-targets += $(dtb-y)
-
-# Rule to build device tree blobs
-$(obj)/%.dtb: $(src)/dts/%.dts FORCE
-       $(call if_changed_dep,dtc)
-
-$(obj)/dtbs: $(addprefix $(obj)/, $(dtb-y))
-
-clean-files := *.dtb
-
 ifneq ($(LOADADDR),)
   UIMAGE_LOADADDR=$(LOADADDR)
 else
@@ -90,7 +78,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 +86,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 90275f0..49ca86e 100644 (file)
@@ -652,6 +652,15 @@ __setup_mmu:       sub     r3, r4, #16384          @ Page directory size
                mov     pc, lr
 ENDPROC(__setup_mmu)
 
+@ Enable unaligned access on v6, to allow better code generation
+@ for the decompressor C code:
+__armv6_mmu_cache_on:
+               mrc     p15, 0, r0, c1, c0, 0   @ read SCTLR
+               bic     r0, r0, #2              @ A (no unaligned access fault)
+               orr     r0, r0, #1 << 22        @ U (v6 unaligned access model)
+               mcr     p15, 0, r0, c1, c0, 0   @ write SCTLR
+               b       __armv4_mmu_cache_on
+
 __arm926ejs_mmu_cache_on:
 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
                mov     r0, #4                  @ put dcache in WT mode
@@ -694,6 +703,9 @@ __armv7_mmu_cache_on:
                bic     r0, r0, #1 << 28        @ clear SCTLR.TRE
                orr     r0, r0, #0x5000         @ I-cache enable, RR cache replacement
                orr     r0, r0, #0x003c         @ write buffer
+               bic     r0, r0, #2              @ A (no unaligned access fault)
+               orr     r0, r0, #1 << 22        @ U (v6 unaligned access model)
+                                               @ (needed for ARM1176)
 #ifdef CONFIG_MMU
 #ifdef CONFIG_CPU_ENDIAN_BE8
                orr     r0, r0, #1 << 25        @ big-endian page tables
@@ -914,7 +926,7 @@ proc_types:
 
                .word   0x0007b000              @ ARMv6
                .word   0x000ff000
-               W(b)    __armv4_mmu_cache_on
+               W(b)    __armv6_mmu_cache_on
                W(b)    __armv4_mmu_cache_off
                W(b)    __armv6_mmu_cache_flush
 
index c1ce813..2624937 100644 (file)
@@ -1,21 +1,37 @@
 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
+# rm9200
+dtb-$(CONFIG_ARCH_AT91) += at91rm9200ek.dtb
+# sam9260
+dtb-$(CONFIG_ARCH_AT91) += animeo_ip.dtb
+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
+dtb-$(CONFIG_ARCH_AT91) += pm9g45.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 +41,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 \
@@ -102,4 +120,12 @@ dtb-$(CONFIG_ARCH_VT8500) += vt8500-bv07.dtb \
        wm8505-ref.dtb \
        wm8650-mid.dtb
 
+targets += dtbs
 endif
+
+# *.dtb used to be generated in the directory above. Clean out the
+# old build results so people don't accidentally use them.
+dtbs: $(addprefix $(obj)/, $(dtb-y))
+       $(Q)rm -f $(obj)/../*.dtb
+
+clean-files := *.dtb
diff --git a/arch/arm/boot/dts/animeo_ip.dts b/arch/arm/boot/dts/animeo_ip.dts
new file mode 100644 (file)
index 0000000..74d92cd
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * animeo_ip.dts - Device Tree file for Somfy Animeo IP Boards
+ *
+ *  Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2 only.
+ */
+
+/dts-v1/;
+/include/ "at91sam9260.dtsi"
+
+/ {
+       model = "Somfy Animeo IP";
+       compatible = "somfy,animeo-ip", "atmel,at91sam9260", "atmel,at91sam9";
+
+       aliases {
+               serial0 = &usart1;
+               serial1 = &usart2;
+               serial2 = &usart0;
+               serial3 = &dbgu;
+               serial4 = &usart3;
+               serial5 = &uart0;
+               serial6 = &uart1;
+       };
+
+       chosen {
+               linux,stdout-path = &usart2;
+       };
+
+       memory {
+               reg = <0x20000000 0x4000000>;
+       };
+
+       clocks {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               main_clock: clock@0 {
+                       compatible = "atmel,osc", "fixed-clock";
+                       clock-frequency = <18432000>;
+               };
+       };
+
+       ahb {
+               apb {
+                       usart0: serial@fffb0000 {
+                               pinctrl-0 = <&pinctrl_usart0 &pinctrl_usart0_rts>;
+                               linux,rs485-enabled-at-boot-time;
+                               status = "okay";
+                       };
+
+                       usart1: serial@fffb4000 {
+                               pinctrl-0 = <&pinctrl_usart1 &pinctrl_usart1_rts>;
+                               linux,rs485-enabled-at-boot-time;
+                               status = "okay";
+                       };
+
+                       usart2: serial@fffb8000 {
+                               pinctrl-0 = <&pinctrl_usart2>;
+                               status = "okay";
+                       };
+
+                       macb0: ethernet@fffc4000 {
+                               pinctrl-0 = <&pinctrl_macb_rmii &pinctrl_macb_rmii_mii>;
+                               phy-mode = "mii";
+                               status = "okay";
+                       };
+
+                       mmc0: mmc@fffa8000 {
+                               pinctrl-0 = <&pinctrl_mmc0_clk
+                                            &pinctrl_mmc0_slot1_cmd_dat0
+                                            &pinctrl_mmc0_slot1_dat1_3>;
+                               status = "okay";
+
+                               slot@1 {
+                                       reg = <1>;
+                                       bus-width = <4>;
+                               };
+                       };
+               };
+
+               nand0: nand@40000000 {
+                       nand-bus-width = <8>;
+                       nand-ecc-mode = "soft";
+                       nand-on-flash-bbt;
+                       status = "okay";
+
+                       at91bootstrap@0 {
+                               label = "at91bootstrap";
+                               reg = <0x0 0x8000>;
+                       };
+
+                       barebox@8000 {
+                               label = "barebox";
+                               reg = <0x8000 0x40000>;
+                       };
+
+                       bareboxenv@48000 {
+                               label = "bareboxenv";
+                               reg = <0x48000 0x8000>;
+                       };
+
+                       user_block@0x50000 {
+                               label = "user_block";
+                               reg = <0x50000 0xb0000>;
+                       };
+
+                       kernel@100000 {
+                               label = "kernel";
+                               reg = <0x100000 0x1b0000>;
+                       };
+
+                       root@2b0000 {
+                               label = "root";
+                               reg = <0x2b0000 0x1D50000>;
+                       };
+               };
+
+               usb0: ohci@00500000 {
+                       num-ports = <2>;
+                       atmel,vbus-gpio = <&pioB 15 1>;
+                       status = "okay";
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               power_green {
+                       label = "power_green";
+                       gpios = <&pioC 17 0>;
+                       linux,default-trigger = "heartbeat";
+               };
+
+               power_red {
+                       label = "power_red";
+                       gpios = <&pioA 2 0>;
+               };
+
+               tx_green {
+                       label = "tx_green";
+                       gpios = <&pioC 19 0>;
+               };
+
+               tx_red {
+                       label = "tx_red";
+                       gpios = <&pioC 18 0>;
+               };
+       };
+
+       gpio_keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               keyswitch_in {
+                       label = "keyswitch_in";
+                       gpios = <&pioB 1 0>;
+                       linux,code = <28>;
+                       gpio-key,wakeup;
+               };
+
+               error_in {
+                       label = "error_in";
+                       gpios = <&pioB 2 0>;
+                       linux,code = <29>;
+                       gpio-key,wakeup;
+               };
+
+               btn {
+                       label = "btn";
+                       gpios = <&pioC 23 0>;
+                       linux,code = <31>;
+                       gpio-key,wakeup;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/at91rm9200.dtsi b/arch/arm/boot/dts/at91rm9200.dtsi
new file mode 100644 (file)
index 0000000..e154f24
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * at91rm9200.dtsi - Device Tree Include file for AT91RM9200 family SoC
+ *
+ *  Copyright (C) 2011 Atmel,
+ *                2011 Nicolas Ferre <nicolas.ferre@atmel.com>,
+ *                2012 Joachim Eastwood <manabian@gmail.com>
+ *
+ * Based on at91sam9260.dtsi
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+       model = "Atmel AT91RM9200 family SoC";
+       compatible = "atmel,at91rm9200";
+       interrupt-parent = <&aic>;
+
+       aliases {
+               serial0 = &dbgu;
+               serial1 = &usart0;
+               serial2 = &usart1;
+               serial3 = &usart2;
+               serial4 = &usart3;
+               gpio0 = &pioA;
+               gpio1 = &pioB;
+               gpio2 = &pioC;
+               gpio3 = &pioD;
+               tcb0 = &tcb0;
+               tcb1 = &tcb1;
+       };
+       cpus {
+               cpu@0 {
+                       compatible = "arm,arm920t";
+               };
+       };
+
+       memory {
+               reg = <0x20000000 0x04000000>;
+       };
+
+       ahb {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               apb {
+                       compatible = "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+
+                       aic: interrupt-controller@fffff000 {
+                               #interrupt-cells = <3>;
+                               compatible = "atmel,at91rm9200-aic";
+                               interrupt-controller;
+                               reg = <0xfffff000 0x200>;
+                               atmel,external-irqs = <25 26 27 28 29 30 31>;
+                       };
+
+                       ramc0: ramc@ffffff00 {
+                               compatible = "atmel,at91rm9200-sdramc";
+                               reg = <0xffffff00 0x100>;
+                       };
+
+                       pmc: pmc@fffffc00 {
+                               compatible = "atmel,at91rm9200-pmc";
+                               reg = <0xfffffc00 0x100>;
+                       };
+
+                       st: timer@fffffd00 {
+                               compatible = "atmel,at91rm9200-st";
+                               reg = <0xfffffd00 0x100>;
+                               interrupts = <1 4 7>;
+                       };
+
+                       tcb0: timer@fffa0000 {
+                               compatible = "atmel,at91rm9200-tcb";
+                               reg = <0xfffa0000 0x100>;
+                               interrupts = <17 4 0 18 4 0 19 4 0>;
+                       };
+
+                       tcb1: timer@fffa4000 {
+                               compatible = "atmel,at91rm9200-tcb";
+                               reg = <0xfffa4000 0x100>;
+                               interrupts = <20 4 0 21 4 0 22 4 0>;
+                       };
+
+                       pinctrl@fffff400 {
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               compatible = "atmel,at91rm9200-pinctrl", "simple-bus";
+                               ranges = <0xfffff400 0xfffff400 0x800>;
+
+                               atmel,mux-mask = <
+                                       /*    A         B     */
+                                        0xffffffff 0xffffffff  /* pioA */
+                                        0xffffffff 0x083fffff  /* pioB */
+                                        0xffff3fff 0x00000000  /* pioC */
+                                        0x03ff87ff 0x0fffff80  /* pioD */
+                                       >;
+
+                               /* shared pinctrl settings */
+                               dbgu {
+                                       pinctrl_dbgu: dbgu-0 {
+                                               atmel,pins =
+                                                       <0 30 0x1 0x0   /* PA30 periph A */
+                                                        0 31 0x1 0x1>; /* PA31 periph with pullup */
+                                       };
+                               };
+
+                               uart0 {
+                                       pinctrl_uart0: uart0-0 {
+                                               atmel,pins =
+                                                       <0 17 0x1 0x0   /* PA17 periph A */
+                                                        0 18 0x1 0x0>; /* PA18 periph A */
+                                       };
+
+                                       pinctrl_uart0_rts: uart0_rts-0 {
+                                               atmel,pins =
+                                                       <0 20 0x1 0x0>; /* PA20 periph A */
+                                       };
+
+                                       pinctrl_uart0_cts: uart0_cts-0 {
+                                               atmel,pins =
+                                                       <0 21 0x1 0x0>; /* PA21 periph A */
+                                       };
+                               };
+
+                               uart1 {
+                                       pinctrl_uart1: uart1-0 {
+                                               atmel,pins =
+                                                       <1 20 0x1 0x1   /* PB20 periph A with pullup */
+                                                        1 21 0x1 0x0>; /* PB21 periph A */
+                                       };
+
+                                       pinctrl_uart1_rts: uart1_rts-0 {
+                                               atmel,pins =
+                                                       <1 24 0x1 0x0>; /* PB24 periph A */
+                                       };
+
+                                       pinctrl_uart1_cts: uart1_cts-0 {
+                                               atmel,pins =
+                                                       <1 26 0x1 0x0>; /* PB26 periph A */
+                                       };
+
+                                       pinctrl_uart1_dtr_dsr: uart1_dtr_dsr-0 {
+                                               atmel,pins =
+                                                       <1 19 0x1 0x0   /* PB19 periph A */
+                                                        1 25 0x1 0x0>; /* PB25 periph A */
+                                       };
+
+                                       pinctrl_uart1_dcd: uart1_dcd-0 {
+                                               atmel,pins =
+                                                       <1 23 0x1 0x0>; /* PB23 periph A */
+                                       };
+
+                                       pinctrl_uart1_ri: uart1_ri-0 {
+                                               atmel,pins =
+                                                       <1 18 0x1 0x0>; /* PB18 periph A */
+                                       };
+                               };
+
+                               uart2 {
+                                       pinctrl_uart2: uart2-0 {
+                                               atmel,pins =
+                                                       <0 22 0x1 0x0   /* PA22 periph A */
+                                                        0 23 0x1 0x1>; /* PA23 periph A with pullup */
+                                       };
+
+                                       pinctrl_uart2_rts: uart2_rts-0 {
+                                               atmel,pins =
+                                                       <0 30 0x2 0x0>; /* PA30 periph B */
+                                       };
+
+                                       pinctrl_uart2_cts: uart2_cts-0 {
+                                               atmel,pins =
+                                                       <0 31 0x2 0x0>; /* PA31 periph B */
+                                       };
+                               };
+
+                               uart3 {
+                                       pinctrl_uart3: uart3-0 {
+                                               atmel,pins =
+                                                       <0 5 0x2 0x1    /* PA5 periph B with pullup */
+                                                        0 6 0x2 0x0>;  /* PA6 periph B */
+                                       };
+
+                                       pinctrl_uart3_rts: uart3_rts-0 {
+                                               atmel,pins =
+                                                       <1 0 0x2 0x0>;  /* PB0 periph B */
+                                       };
+
+                                       pinctrl_uart3_cts: uart3_cts-0 {
+                                               atmel,pins =
+                                                       <1 1 0x2 0x0>;  /* PB1 periph B */
+                                       };
+                               };
+
+                               nand {
+                                       pinctrl_nand: nand-0 {
+                                               atmel,pins =
+                                                       <2 2 0x0 0x1    /* PC2 gpio RDY pin pull_up */
+                                                        1 1 0x0 0x1>;  /* PB1 gpio CD 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>;
+                               };
+
+                               pioD: 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@fffff200 {
+                               compatible = "atmel,at91rm9200-usart";
+                               reg = <0xfffff200 0x200>;
+                               interrupts = <1 4 7>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_dbgu>;
+                               status = "disabled";
+                       };
+
+                       usart0: serial@fffc0000 {
+                               compatible = "atmel,at91rm9200-usart";
+                               reg = <0xfffc0000 0x200>;
+                               interrupts = <6 4 5>;
+                               atmel,use-dma-rx;
+                               atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart0>;
+                               status = "disabled";
+                       };
+
+                       usart1: serial@fffc4000 {
+                               compatible = "atmel,at91rm9200-usart";
+                               reg = <0xfffc4000 0x200>;
+                               interrupts = <7 4 5>;
+                               atmel,use-dma-rx;
+                               atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart1>;
+                               status = "disabled";
+                       };
+
+                       usart2: serial@fffc8000 {
+                               compatible = "atmel,at91rm9200-usart";
+                               reg = <0xfffc8000 0x200>;
+                               interrupts = <8 4 5>;
+                               atmel,use-dma-rx;
+                               atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart2>;
+                               status = "disabled";
+                       };
+
+                       usart3: serial@fffcc000 {
+                               compatible = "atmel,at91rm9200-usart";
+                               reg = <0xfffcc000 0x200>;
+                               interrupts = <23 4 5>;
+                               atmel,use-dma-rx;
+                               atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart3>;
+                               status = "disabled";
+                       };
+
+                       usb1: gadget@fffb0000 {
+                               compatible = "atmel,at91rm9200-udc";
+                               reg = <0xfffb0000 0x4000>;
+                               interrupts = <11 4 2>;
+                               status = "disabled";
+                       };
+               };
+
+               nand0: nand@40000000 {
+                       compatible = "atmel,at91rm9200-nand";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0x40000000 0x10000000>;
+                       atmel,nand-addr-offset = <21>;
+                       atmel,nand-cmd-offset = <22>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_nand>;
+                       nand-ecc-mode = "soft";
+                       gpios = <&pioC 2 0
+                                0
+                                &pioB 1 0
+                               >;
+                       status = "disabled";
+               };
+
+               usb0: ohci@00300000 {
+                       compatible = "atmel,at91rm9200-ohci", "usb-ohci";
+                       reg = <0x00300000 0x100000>;
+                       interrupts = <23 4 2>;
+                       status = "disabled";
+               };
+       };
+
+       i2c@0 {
+               compatible = "i2c-gpio";
+               gpios = <&pioA 23 0 /* sda */
+                        &pioA 24 0 /* scl */
+                       >;
+               i2c-gpio,sda-open-drain;
+               i2c-gpio,scl-open-drain;
+               i2c-gpio,delay-us = <2>;        /* ~100 kHz */
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
+       };
+};
diff --git a/arch/arm/boot/dts/at91rm9200ek.dts b/arch/arm/boot/dts/at91rm9200ek.dts
new file mode 100644 (file)
index 0000000..8aa4893
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * at91rm9200ek.dts - Device Tree file for Atmel AT91RM9200 evaluation kit
+ *
+ *  Copyright (C) 2012 Joachim Eastwood <manabian@gmail.com>
+ *
+ * Licensed under GPLv2 only
+ */
+/dts-v1/;
+/include/ "at91rm9200.dtsi"
+
+/ {
+       model = "Atmel AT91RM9200 evaluation kit";
+       compatible = "atmel,at91rm9200ek", "atmel,at91rm9200";
+
+       memory {
+               reg = <0x20000000 0x4000000>;
+       };
+
+       clocks {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               main_clock: clock@0 {
+                       compatible = "atmel,osc", "fixed-clock";
+                       clock-frequency = <18432000>;
+               };
+       };
+
+       ahb {
+               apb {
+                       dbgu: serial@fffff200 {
+                               status = "okay";
+                       };
+
+                       usart1: serial@fffc4000 {
+                               pinctrl-0 =
+                                               <&pinctrl_uart1
+                                                &pinctrl_uart1_rts
+                                                &pinctrl_uart1_cts
+                                                &pinctrl_uart1_dtr_dsr
+                                                &pinctrl_uart1_dcd
+                                                &pinctrl_uart1_ri>;
+                               status = "okay";
+                       };
+
+                       usb1: gadget@fffb0000 {
+                               atmel,vbus-gpio = <&pioD 4 0>;
+                               status = "okay";
+                       };
+               };
+
+               usb0: ohci@00300000 {
+                       num-ports = <2>;
+                       status = "okay";
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               ds2 {
+                       label = "green";
+                       gpios = <&pioB 0 0x1>;
+                       linux,default-trigger = "mmc0";
+               };
+
+               ds4 {
+                       label = "yellow";
+                       gpios = <&pioB 1 0x1>;
+                       linux,default-trigger = "heartbeat";
+               };
+
+               ds6 {
+                       label = "red";
+                       gpios = <&pioB 2 0x1>;
+               };
+       };
+};
index d410581..b1d3fab 100644 (file)
@@ -21,8 +21,8 @@
                serial2 = &usart1;
                serial3 = &usart2;
                serial4 = &usart3;
-               serial5 = &usart4;
-               serial6 = &usart5;
+               serial5 = &uart0;
+               serial6 = &uart1;
                gpio0 = &pioA;
                gpio1 = &pioB;
                gpio2 = &pioC;
                                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>;
-                       };
+                               usart0 {
+                                       pinctrl_usart0: usart0-0 {
+                                               atmel,pins =
+                                                       <1 4 0x1 0x0    /* PB4 periph A */
+                                                        1 5 0x1 0x0>;  /* PB5 periph A */
+                                       };
+
+                                       pinctrl_usart0_rts: usart0_rts-0 {
+                                               atmel,pins =
+                                                       <1 26 0x1 0x0>; /* PB26 periph A */
+                                       };
+
+                                       pinctrl_usart0_cts: usart0_cts-0 {
+                                               atmel,pins =
+                                                       <1 27 0x1 0x0>; /* PB27 periph A */
+                                       };
+
+                                       pinctrl_usart0_dtr_dsr: usart0_dtr_dsr-0 {
+                                               atmel,pins =
+                                                       <1 24 0x1 0x0   /* PB24 periph A */
+                                                        1 22 0x1 0x0>; /* PB22 periph A */
+                                       };
+
+                                       pinctrl_usart0_dcd: usart0_dcd-0 {
+                                               atmel,pins =
+                                                       <1 23 0x1 0x0>; /* PB23 periph A */
+                                       };
+
+                                       pinctrl_usart0_ri: usart0_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>;
+                               usart1 {
+                                       pinctrl_usart1: usart1-0 {
+                                               atmel,pins =
+                                                       <2 6 0x1 0x1    /* PB6 periph A with pullup */
+                                                        2 7 0x1 0x0>;  /* PB7 periph A */
+                                       };
+
+                                       pinctrl_usart1_rts: usart1_rts-0 {
+                                               atmel,pins =
+                                                       <1 28 0x1 0x0>; /* PB28 periph A */
+                                       };
+
+                                       pinctrl_usart1_cts: usart1_cts-0 {
+                                               atmel,pins =
+                                                       <1 29 0x1 0x0>; /* PB29 periph A */
+                                       };
+                               };
+
+                               usart2 {
+                                       pinctrl_usart2: usart2-0 {
+                                               atmel,pins =
+                                                       <1 8 0x1 0x1    /* PB8 periph A with pullup */
+                                                        1 9 0x1 0x0>;  /* PB9 periph A */
+                                       };
+
+                                       pinctrl_usart2_rts: usart2_rts-0 {
+                                               atmel,pins =
+                                                       <0 4 0x1 0x0>;  /* PA4 periph A */
+                                       };
+
+                                       pinctrl_usart2_cts: usart2_cts-0 {
+                                               atmel,pins =
+                                                       <0 5 0x1 0x0>;  /* PA5 periph A */
+                                       };
+                               };
+
+                               usart3 {
+                                       pinctrl_usart3: usart3-0 {
+                                               atmel,pins =
+                                                       <2 10 0x1 0x1   /* PB10 periph A with pullup */
+                                                        2 11 0x1 0x0>; /* PB11 periph A */
+                                       };
+
+                                       pinctrl_usart3_rts: usart3_rts-0 {
+                                               atmel,pins =
+                                                       <3 8 0x2 0x0>;  /* PB8 periph B */
+                                       };
+
+                                       pinctrl_usart3_cts: usart3_cts-0 {
+                                               atmel,pins =
+                                                       <3 10 0x2 0x0>; /* PB10 periph B */
+                                       };
+                               };
+
+                               uart0 {
+                                       pinctrl_uart0: uart0-0 {
+                                               atmel,pins =
+                                                       <0 31 0x2 0x1   /* PA31 periph B with pullup */
+                                                        0 30 0x2 0x0>; /* PA30 periph B */
+                                       };
+                               };
+
+                               uart1 {
+                                       pinctrl_uart1: uart1-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 */
+                                       };
+                               };
+
+                               macb {
+                                       pinctrl_macb_rmii: macb_rmii-0 {
+                                               atmel,pins =
+                                                       <0 12 0x1 0x0   /* PA12 periph A */
+                                                        0 13 0x1 0x0   /* PA13 periph A */
+                                                        0 14 0x1 0x0   /* PA14 periph A */
+                                                        0 15 0x1 0x0   /* PA15 periph A */
+                                                        0 16 0x1 0x0   /* PA16 periph A */
+                                                        0 17 0x1 0x0   /* PA17 periph A */
+                                                        0 18 0x1 0x0   /* PA18 periph A */
+                                                        0 19 0x1 0x0   /* PA19 periph A */
+                                                        0 20 0x1 0x0   /* PA20 periph A */
+                                                        0 21 0x1 0x0>; /* PA21 periph A */
+                                       };
+
+                                       pinctrl_macb_rmii_mii: macb_rmii_mii-0 {
+                                               atmel,pins =
+                                                       <0 22 0x2 0x0   /* PA22 periph B */
+                                                        0 23 0x2 0x0   /* PA23 periph B */
+                                                        0 24 0x2 0x0   /* PA24 periph B */
+                                                        0 25 0x2 0x0   /* PA25 periph B */
+                                                        0 26 0x2 0x0   /* PA26 periph B */
+                                                        0 27 0x2 0x0   /* PA27 periph B */
+                                                        0 28 0x2 0x0   /* PA28 periph B */
+                                                        0 29 0x2 0x0>; /* PA29 periph B */
+                                       };
+
+                                       pinctrl_macb_rmii_mii_alt: macb_rmii_mii-1 {
+                                               atmel,pins =
+                                                       <0 10 0x2 0x0   /* PA10 periph B */
+                                                        0 11 0x2 0x0   /* PA11 periph B */
+                                                        0 24 0x2 0x0   /* PA24 periph B */
+                                                        0 25 0x2 0x0   /* PA25 periph B */
+                                                        0 26 0x2 0x0   /* PA26 periph B */
+                                                        0 27 0x2 0x0   /* PA27 periph B */
+                                                        0 28 0x2 0x0   /* PA28 periph B */
+                                                        0 29 0x2 0x0>; /* PA29 periph B */
+                                       };
+                               };
+
+                               mmc0 {
+                                       pinctrl_mmc0_clk: mmc0_clk-0 {
+                                               atmel,pins =
+                                                       <0 8 0x1 0x0>;  /* PA8 periph A */
+                                       };
+
+                                       pinctrl_mmc0_slot0_cmd_dat0: mmc0_slot0_cmd_dat0-0 {
+                                               atmel,pins =
+                                                       <0 7 0x1 0x1    /* PA7 periph A with pullup */
+                                                        0 6 0x1 0x1>;  /* PA6 periph A with pullup */
+                                       };
+
+                                       pinctrl_mmc0_slot0_dat1_3: mmc0_slot0_dat1_3-0 {
+                                               atmel,pins =
+                                                       <0 9 0x1 0x1    /* PA9 periph A with pullup */
+                                                        0 10 0x1 0x1   /* PA10 periph A with pullup */
+                                                        0 11 0x1 0x1>; /* PA11 periph A with pullup */
+                                       };
+
+                                       pinctrl_mmc0_slot1_cmd_dat0: mmc0_slot1_cmd_dat0-0 {
+                                               atmel,pins =
+                                                       <0 1 0x2 0x1    /* PA1 periph B with pullup */
+                                                        0 0 0x2 0x1>;  /* PA0 periph B with pullup */
+                                       };
+
+                                       pinctrl_mmc0_slot1_dat1_3: mmc0_slot1_dat1_3-0 {
+                                               atmel,pins =
+                                                       <0 5 0x2 0x1    /* PA5 periph B with pullup */
+                                                        0 4 0x2 0x1    /* PA4 periph B with pullup */
+                                                        0 3 0x2 0x1>;  /* PA3 periph B with pullup */
+                                       };
+                               };
+
+                               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_usart0>;
                                status = "disabled";
                        };
 
                                interrupts = <7 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_usart1>;
                                status = "disabled";
                        };
 
                                interrupts = <8 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_usart2>;
                                status = "disabled";
                        };
 
                                interrupts = <23 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_usart3>;
                                status = "disabled";
                        };
 
-                       usart4: serial@fffd4000 {
+                       uart0: serial@fffd4000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfffd4000 0x200>;
                                interrupts = <24 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart0>;
                                status = "disabled";
                        };
 
-                       usart5: serial@fffd8000 {
+                       uart1: serial@fffd8000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfffd8000 0x200>;
                                interrupts = <25 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_uart1>;
                                status = "disabled";
                        };
 
                                compatible = "cdns,at32ap7000-macb", "cdns,macb";
                                reg = <0xfffc4000 0x100>;
                                interrupts = <21 4 3>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_macb_rmii>;
                                status = "disabled";
                        };
 
                                status = "disabled";
                        };
 
+                       mmc0: mmc@fffa8000 {
+                               compatible = "atmel,hsmci";
+                               reg = <0xfffa8000 0x600>;
+                               interrupts = <9 4 0>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
                        adc0: adc@fffe0000 {
                                compatible = "atmel,at91sam9260-adc";
                                reg = <0xfffe0000 0x100>;
                              >;
                        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 3e6e5c1..66106ee 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>;
-                       };
+                               usart0 {
+                                       pinctrl_usart0: usart0-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_usart0_rts: usart0_rts-0 {
+                                               atmel,pins =
+                                                       <0 28 0x1 0x0>; /* PA28 periph A */
+                                       };
+
+                                       pinctrl_usart0_cts: usart0_cts-0 {
+                                               atmel,pins =
+                                                       <0 29 0x1 0x0>; /* PA29 periph A */
+                                       };
+                               };
+
+                               usart1 {
+                                       pinctrl_usart1: usart1-0 {
+                                               atmel,pins =
+                                                       <3 0 0x1 0x1    /* PD0 periph A with pullup */
+                                                        3 1 0x1 0x0>;  /* PD1 periph A */
+                                       };
+
+                                       pinctrl_usart1_rts: usart1_rts-0 {
+                                               atmel,pins =
+                                                       <3 7 0x2 0x0>;  /* PD7 periph B */
+                                       };
+
+                                       pinctrl_usart1_cts: usart1_cts-0 {
+                                               atmel,pins =
+                                                       <3 8 0x2 0x0>;  /* PD8 periph B */
+                                       };
+                               };
+
+                               usart2 {
+                                       pinctrl_usart2: usart2-0 {
+                                               atmel,pins =
+                                                       <3 2 0x1 0x1    /* PD2 periph A with pullup */
+                                                        3 3 0x1 0x0>;  /* PD3 periph A */
+                                       };
+
+                                       pinctrl_usart2_rts: usart2_rts-0 {
+                                               atmel,pins =
+                                                       <3 5 0x2 0x0>;  /* PD5 periph B */
+                                       };
+
+                                       pinctrl_usart2_cts: usart2_cts-0 {
+                                               atmel,pins =
+                                                       <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 */
+                                       };
+                               };
+
+                               macb {
+                                       pinctrl_macb_rmii: macb_rmii-0 {
+                                               atmel,pins =
+                                                       <2 25 0x2 0x0   /* PC25 periph B */
+                                                        4 21 0x1 0x0   /* PE21 periph A */
+                                                        4 23 0x1 0x0   /* PE23 periph A */
+                                                        4 24 0x1 0x0   /* PE24 periph A */
+                                                        4 25 0x1 0x0   /* PE25 periph A */
+                                                        4 26 0x1 0x0   /* PE26 periph A */
+                                                        4 27 0x1 0x0   /* PE27 periph A */
+                                                        4 28 0x1 0x0   /* PE28 periph A */
+                                                        4 29 0x1 0x0   /* PE29 periph A */
+                                                        4 30 0x1 0x0>; /* PE30 periph A */
+                                       };
+
+                                       pinctrl_macb_rmii_mii: macb_rmii_mii-0 {
+                                               atmel,pins =
+                                                       <2 20 0x2 0x0   /* PC20 periph B */
+                                                        2 21 0x2 0x0   /* PC21 periph B */
+                                                        2 22 0x2 0x0   /* PC22 periph B */
+                                                        2 23 0x2 0x0   /* PC23 periph B */
+                                                        2 24 0x2 0x0   /* PC24 periph B */
+                                                        2 25 0x2 0x0   /* PC25 periph B */
+                                                        2 27 0x2 0x0   /* PC27 periph B */
+                                                        4 22 0x2 0x0>; /* PE22 periph B */
+                                       };
+                               };
+
+                               mmc0 {
+                                       pinctrl_mmc0_clk: mmc0_clk-0 {
+                                               atmel,pins =
+                                                       <0 12 0x1 0x0>; /* PA12 periph A */
+                                       };
+
+                                       pinctrl_mmc0_slot0_cmd_dat0: mmc0_slot0_cmd_dat0-0 {
+                                               atmel,pins =
+                                                       <0 1 0x1 0x1    /* PA1 periph A with pullup */
+                                                        0 0 0x1 0x1>;  /* PA0 periph A with pullup */
+                                       };
+
+                                       pinctrl_mmc0_slot0_dat1_3: mmc0_slot0_dat1_3-0 {
+                                               atmel,pins =
+                                                       <0 3 0x1 0x1    /* PA3 periph A with pullup */
+                                                        0 4 0x1 0x1    /* PA4 periph A with pullup */
+                                                        0 5 0x1 0x1>;  /* PA5 periph A with pullup */
+                                       };
+
+                                       pinctrl_mmc0_slot1_cmd_dat0: mmc0_slot1_cmd_dat0-0 {
+                                               atmel,pins =
+                                                       <0 16 0x1 0x1   /* PA16 periph A with pullup */
+                                                        0 17 0x1 0x1>; /* PA17 periph A with pullup */
+                                       };
+
+                                       pinctrl_mmc0_slot1_dat1_3: mmc0_slot1_dat1_3-0 {
+                                               atmel,pins =
+                                                       <0 18 0x1 0x1   /* PA18 periph A with pullup */
+                                                        0 19 0x1 0x1   /* PA19 periph A with pullup */
+                                                        0 20 0x1 0x1>; /* PA20 periph A with pullup */
+                                       };
+                               };
+
+                               mmc1 {
+                                       pinctrl_mmc1_clk: mmc1_clk-0 {
+                                               atmel,pins =
+                                                       <0 6 0x1 0x0>;  /* PA6 periph A */
+                                       };
+
+                                       pinctrl_mmc1_slot0_cmd_dat0: mmc1_slot0_cmd_dat0-0 {
+                                               atmel,pins =
+                                                       <0 7 0x1 0x1    /* PA7 periph A with pullup */
+                                                        0 8 0x1 0x1>;  /* PA8 periph A with pullup */
+                                       };
+
+                                       pinctrl_mmc1_slot0_dat1_3: mmc1_slot0_dat1_3-0 {
+                                               atmel,pins =
+                                                       <0 9 0x1 0x1    /* PA9 periph A with pullup */
+                                                        0 10 0x1 0x1   /* PA10 periph A with pullup */
+                                                        0 11 0x1 0x1>; /* PA11 periph A with pullup */
+                                       };
+
+                                       pinctrl_mmc1_slot1_cmd_dat0: mmc1_slot1_cmd_dat0-0 {
+                                               atmel,pins =
+                                                       <0 21 0x1 0x1   /* PA21 periph A with pullup */
+                                                        0 22 0x1 0x1>; /* PA22 periph A with pullup */
+                                       };
+
+                                       pinctrl_mmc1_slot1_dat1_3: mmc1_slot1_dat1_3-0 {
+                                               atmel,pins =
+                                                       <0 23 0x1 0x1   /* PA23 periph A with pullup */
+                                                        0 24 0x1 0x1   /* PA24 periph A with pullup */
+                                                        0 25 0x1 0x1>; /* PA25 periph A with pullup */
+                                       };
+                               };
+
+                               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_usart0>;
                                status = "disabled";
                        };
 
                                interrupts = <8 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_usart1>;
                                status = "disabled";
                        };
 
                                interrupts = <9 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_usart2>;
                                status = "disabled";
                        };
 
                                compatible = "cdns,at32ap7000-macb", "cdns,macb";
                                reg = <0xfffbc000 0x100>;
                                interrupts = <21 4 3>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_macb_rmii>;
                                status = "disabled";
                        };
 
                                #size-cells = <0>;
                                status = "disabled";
                        };
+
+                       mmc0: mmc@fff80000 {
+                               compatible = "atmel,hsmci";
+                               reg = <0xfff80000 0x600>;
+                               interrupts = <10 4 0>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       mmc1: mmc@fff84000 {
+                               compatible = "atmel,hsmci";
+                               reg = <0xfff84000 0x600>;
+                               interrupts = <11 4 0>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
                };
 
                nand0: nand@40000000 {
                              >;
                        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 f86ac4b..1eb0872 100644 (file)
                        };
 
                        usart0: serial@fff8c000 {
+                               pinctrl-0 = <
+                                       &pinctrl_usart0
+                                       &pinctrl_usart0_rts
+                                       &pinctrl_usart0_cts>;
                                status = "okay";
                        };
 
                                atmel,vbus-gpio = <&pioA 25 0>;
                                status = "okay";
                        };
+
+                       mmc0: mmc@fff80000 {
+                               pinctrl-0 = <
+                                       &pinctrl_board_mmc0
+                                       &pinctrl_mmc0_clk
+                                       &pinctrl_mmc0_slot0_cmd_dat0
+                                       &pinctrl_mmc0_slot0_dat1_3>;
+                               status = "okay";
+                               slot@0 {
+                                       reg = <0>;
+                                       bus-width = <4>;
+                                       cd-gpios = <&pioE 18 0>;
+                                       wp-gpios = <&pioE 19 0>;
+                               };
+                       };
+
+                       pinctrl@fffff200 {
+                               mmc0 {
+                                       pinctrl_board_mmc0: mmc0-board {
+                                               atmel,pins =
+                                                       <5 18 0x0 0x5   /* PE18 gpio CD pin pull up and deglitch */
+                                                        5 19 0x0 0x1>; /* PE19 gpio WP pin pull up */
+                                       };
+                               };
+                       };
                };
 
                nand0: nand@40000000 {
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 f1b2e14..66467b1 100644 (file)
        model = "Atmel at91sam9g20ek 2 mmc";
        compatible = "atmel,at91sam9g20ek_2mmc", "atmel,at91sam9g20", "atmel,at91sam9";
 
+       ahb {
+               apb{
+                       mmc0: mmc@fffa8000 {
+                               /* clk already mux wuth slot0 */
+                               pinctrl-0 = <
+                                       &pinctrl_board_mmc0_slot0
+                                       &pinctrl_mmc0_slot0_cmd_dat0
+                                       &pinctrl_mmc0_slot0_dat1_3>;
+                               slot@0 {
+                                       reg = <0>;
+                                       bus-width = <4>;
+                                       cd-gpios = <&pioC 2 0>;
+                               };
+                       };
+
+                       pinctrl@fffff400 {
+                               mmc0_slot0 {
+                                       pinctrl_board_mmc0_slot0: mmc0_slot0-board {
+                                               atmel,pins =
+                                                       <2 2 0x0 0x5>;  /* PC2 gpio CD pin pull up and deglitch */
+                                       };
+                               };
+                       };
+               };
+       };
+
        leds {
                compatible = "gpio-leds";
 
index b06c0db..32a500a 100644 (file)
                        };
 
                        usart0: serial@fffb0000 {
+                               pinctrl-0 =
+                                       <&pinctrl_usart0
+                                        &pinctrl_usart0_rts
+                                        &pinctrl_usart0_cts
+                                        &pinctrl_usart0_dtr_dsr
+                                        &pinctrl_usart0_dcd
+                                        &pinctrl_usart0_ri>;
                                status = "okay";
                        };
 
                                atmel,vbus-gpio = <&pioC 5 0>;
                                status = "okay";
                        };
+
+                       mmc0: mmc@fffa8000 {
+                               pinctrl-0 = <
+                                       &pinctrl_board_mmc0_slot1
+                                       &pinctrl_mmc0_clk
+                                       &pinctrl_mmc0_slot1_cmd_dat0
+                                       &pinctrl_mmc0_slot1_dat1_3>;
+                               status = "okay";
+                               slot@1 {
+                                       reg = <1>;
+                                       bus-width = <4>;
+                                       cd-gpios = <&pioC 9 0>;
+                               };
+                       };
+
+                       pinctrl@fffff400 {
+                               mmc0_slot1 {
+                                       pinctrl_board_mmc0_slot1: mmc0_slot1-board {
+                                               atmel,pins =
+                                                       <2 9 0x0 0x5>;  /* PC9 gpio CD pin pull up and deglitch */
+                                       };
+                               };
+                       };
                };
 
                nand0: nand@40000000 {
                #size-cells = <0>;
 
                btn3 {
-                       label = "Buttin 3";
+                       label = "Button 3";
                        gpios = <&pioA 30 1>;
                        linux,code = <0x103>;
                        gpio-key,wakeup;
                };
 
                btn4 {
-                       label = "Buttin 4";
+                       label = "Button 4";
                        gpios = <&pioA 31 1>;
                        linux,code = <0x104>;
                        gpio-key,wakeup;
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 877c08f..c5ab16f 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 3add030..0741cae 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>;
-                       };
+                               usart0 {
+                                       pinctrl_usart0: usart0-0 {
+                                               atmel,pins =
+                                                       <1 19 0x1 0x1   /* PB19 periph A with pullup */
+                                                        1 18 0x1 0x0>; /* PB18 periph A */
+                                       };
+
+                                       pinctrl_usart0_rts: usart0_rts-0 {
+                                               atmel,pins =
+                                                       <1 17 0x2 0x0>; /* PB17 periph B */
+                                       };
+
+                                       pinctrl_usart0_cts: usart0_cts-0 {
+                                               atmel,pins =
+                                                       <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_usart1: usart1-0 {
+                                               atmel,pins =
+                                                       <1 4 0x1 0x1    /* PB4 periph A with pullup */
+                                                        1 5 0x1 0x0>;  /* PB5 periph A */
+                                       };
+
+                                       pinctrl_usart1_rts: usart1_rts-0 {
+                                               atmel,pins =
+                                                       <3 16 0x1 0x0>; /* PD16 periph A */
+                                       };
+
+                                       pinctrl_usart1_cts: usart1_cts-0 {
+                                               atmel,pins =
+                                                       <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>;
-                       };
+                               usart2 {
+                                       pinctrl_usart2: usart2-0 {
+                                               atmel,pins =
+                                                       <1 6 0x1 0x1    /* PB6 periph A with pullup */
+                                                        1 7 0x1 0x0>;  /* PB7 periph A */
+                                       };
+
+                                       pinctrl_usart2_rts: usart2_rts-0 {
+                                               atmel,pins =
+                                                       <2 9 0x2 0x0>;  /* PC9 periph B */
+                                       };
+
+                                       pinctrl_usart2_cts: usart2_cts-0 {
+                                               atmel,pins =
+                                                       <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>;
+                               usart3 {
+                                       pinctrl_usart3: usart3-0 {
+                                               atmel,pins =
+                                                       <1 8 0x1 0x1    /* PB9 periph A with pullup */
+                                                        1 9 0x1 0x0>;  /* PB8 periph A */
+                                       };
+
+                                       pinctrl_usart3_rts: usart3_rts-0 {
+                                               atmel,pins =
+                                                       <0 23 0x2 0x0>; /* PA23 periph B */
+                                       };
+
+                                       pinctrl_usart3_cts: usart3_cts-0 {
+                                               atmel,pins =
+                                                       <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 */
+                                       };
+                               };
+
+                               macb {
+                                       pinctrl_macb_rmii: macb_rmii-0 {
+                                               atmel,pins =
+                                                       <0 10 0x1 0x0   /* PA10 periph A */
+                                                        0 11 0x1 0x0   /* PA11 periph A */
+                                                        0 12 0x1 0x0   /* PA12 periph A */
+                                                        0 13 0x1 0x0   /* PA13 periph A */
+                                                        0 14 0x1 0x0   /* PA14 periph A */
+                                                        0 15 0x1 0x0   /* PA15 periph A */
+                                                        0 16 0x1 0x0   /* PA16 periph A */
+                                                        0 17 0x1 0x0   /* PA17 periph A */
+                                                        0 18 0x1 0x0   /* PA18 periph A */
+                                                        0 19 0x1 0x0>; /* PA19 periph A */
+                                       };
+
+                                       pinctrl_macb_rmii_mii: macb_rmii_mii-0 {
+                                               atmel,pins =
+                                                       <0 6 0x2 0x0    /* PA6 periph B */
+                                                        0 7 0x2 0x0    /* PA7 periph B */
+                                                        0 8 0x2 0x0    /* PA8 periph B */
+                                                        0 9 0x2 0x0    /* PA9 periph B */
+                                                        0 27 0x2 0x0   /* PA27 periph B */
+                                                        0 28 0x2 0x0   /* PA28 periph B */
+                                                        0 29 0x2 0x0   /* PA29 periph B */
+                                                        0 30 0x2 0x0>; /* PA30 periph B */
+                                       };
+                               };
+
+                               mmc0 {
+                                       pinctrl_mmc0_slot0_clk_cmd_dat0: mmc0_slot0_clk_cmd_dat0-0 {
+                                               atmel,pins =
+                                                       <0 0 0x1 0x0    /* PA0 periph A */
+                                                        0 1 0x1 0x1    /* PA1 periph A with pullup */
+                                                        0 2 0x1 0x1>;  /* PA2 periph A with pullup */
+                                       };
+
+                                       pinctrl_mmc0_slot0_dat1_3: mmc0_slot0_dat1_3-0 {
+                                               atmel,pins =
+                                                       <0 3 0x1 0x1    /* PA3 periph A with pullup */
+                                                        0 4 0x1 0x1    /* PA4 periph A with pullup */
+                                                        0 5 0x1 0x1>;  /* PA5 periph A with pullup */
+                                       };
+
+                                       pinctrl_mmc0_slot0_dat4_7: mmc0_slot0_dat4_7-0 {
+                                               atmel,pins =
+                                                       <0 6 0x1 0x1    /* PA6 periph A with pullup */
+                                                        0 7 0x1 0x1    /* PA7 periph A with pullup */
+                                                        0 8 0x1 0x1    /* PA8 periph A with pullup */
+                                                        0 9 0x1 0x1>;  /* PA9 periph A with pullup */
+                                       };
+                               };
+
+                               mmc1 {
+                                       pinctrl_mmc1_slot0_clk_cmd_dat0: mmc1_slot0_clk_cmd_dat0-0 {
+                                               atmel,pins =
+                                                       <0 31 0x1 0x0   /* PA31 periph A */
+                                                        0 22 0x1 0x1   /* PA22 periph A with pullup */
+                                                        0 23 0x1 0x1>; /* PA23 periph A with pullup */
+                                       };
+
+                                       pinctrl_mmc1_slot0_dat1_3: mmc1_slot0_dat1_3-0 {
+                                               atmel,pins =
+                                                       <0 24 0x1 0x1   /* PA24 periph A with pullup */
+                                                        0 25 0x1 0x1   /* PA25 periph A with pullup */
+                                                        0 26 0x1 0x1>; /* PA26 periph A with pullup */
+                                       };
+
+                                       pinctrl_mmc1_slot0_dat4_7: mmc1_slot0_dat4_7-0 {
+                                               atmel,pins =
+                                                       <0 27 0x1 0x1   /* PA27 periph A with pullup */
+                                                        0 28 0x1 0x1   /* PA28 periph A with pullup */
+                                                        0 29 0x1 0x1   /* PA29 periph A with pullup */
+                                                        0 20 0x1 0x1>; /* PA30 periph A with pullup */
+                                       };
+                               };
+
+                               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_usart0>;
                                status = "disabled";
                        };
 
                                interrupts = <8 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_usart1>;
                                status = "disabled";
                        };
 
                                interrupts = <9 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_usart2>;
                                status = "disabled";
                        };
 
                                interrupts = <10 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_usart3>;
                                status = "disabled";
                        };
 
                                compatible = "cdns,at32ap7000-macb", "cdns,macb";
                                reg = <0xfffbc000 0x100>;
                                interrupts = <25 4 3>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_macb_rmii>;
                                status = "disabled";
                        };
 
                                        trigger-value = <0x6>;
                                };
                        };
+
+                       mmc0: mmc@fff80000 {
+                               compatible = "atmel,hsmci";
+                               reg = <0xfff80000 0x600>;
+                               interrupts = <11 4 0>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       mmc1: mmc@fffd0000 {
+                               compatible = "atmel,hsmci";
+                               reg = <0xfffd0000 0x600>;
+                               interrupts = <29 4 0>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
                };
 
                nand0: nand@40000000 {
                              >;
                        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 15e1dd4..20c3191 100644 (file)
                        };
 
                        usart1: serial@fff90000 {
+                               pinctrl-0 =
+                                       <&pinctrl_usart1
+                                        &pinctrl_usart1_rts
+                                        &pinctrl_usart1_cts>;
                                status = "okay";
                        };
 
                        i2c1: i2c@fff88000 {
                                status = "okay";
                        };
+
+                       mmc0: mmc@fff80000 {
+                               pinctrl-0 = <
+                                       &pinctrl_board_mmc0
+                                       &pinctrl_mmc0_slot0_clk_cmd_dat0
+                                       &pinctrl_mmc0_slot0_dat1_3>;
+                               status = "okay";
+                               slot@0 {
+                                       reg = <0>;
+                                       bus-width = <4>;
+                                       cd-gpios = <&pioD 10 0>;
+                               };
+                       };
+
+                       mmc1: mmc@fffd0000 {
+                               pinctrl-0 = <
+                                       &pinctrl_board_mmc1
+                                       &pinctrl_mmc1_slot0_clk_cmd_dat0
+                                       &pinctrl_mmc1_slot0_dat1_3>;
+                               status = "okay";
+                               slot@0 {
+                                       reg = <0>;
+                                       bus-width = <4>;
+                                       cd-gpios = <&pioD 11 0>;
+                                       wp-gpios = <&pioD 29 0>;
+                               };
+                       };
+
+                       pinctrl@fffff200 {
+                               mmc0 {
+                                       pinctrl_board_mmc0: mmc0-board {
+                                               atmel,pins =
+                                                       <3 10 0x0 0x5>; /* PD10 gpio CD pin pull up and deglitch */
+                                       };
+                               };
+
+                               mmc1 {
+                                       pinctrl_board_mmc1: mmc1-board {
+                                               atmel,pins =
+                                                       <3 11 0x0 0x5   /* PD11 gpio CD pin pull up and deglitch */
+                                                        3 29 0x0 0x1>; /* PD29 gpio WP pin pull up */
+                                       };
+                               };
+                       };
                };
 
                nand0: nand@40000000 {
index 82508d6..e9efb34 100644 (file)
                                reg = <0xfffffe10 0x10>;
                        };
 
+                       mmc0: mmc@f0008000 {
+                               compatible = "atmel,hsmci";
+                               reg = <0xf0008000 0x600>;
+                               interrupts = <12 4 0>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
                        tcb0: timer@f8008000 {
                                compatible = "atmel,at91sam9x5-tcb";
                                reg = <0xf8008000 0x100>;
                                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>;
+                               usart0 {
+                                       pinctrl_usart0: usart0-0 {
+                                               atmel,pins =
+                                                       <0 1 0x1 0x1    /* PA1 periph A with pullup */
+                                                        0 0 0x1 0x0>;  /* PA0 periph A */
+                                       };
+
+                                       pinctrl_usart0_rts: usart0_rts-0 {
+                                               atmel,pins =
+                                                       <0 2 0x1 0x0>;  /* PA2 periph A */
+                                       };
+
+                                       pinctrl_usart0_cts: usart0_cts-0 {
+                                               atmel,pins =
+                                                       <0 3 0x1 0x0>;  /* PA3 periph A */
+                                       };
+                               };
+
+                               usart1 {
+                                       pinctrl_usart1: usart1-0 {
+                                               atmel,pins =
+                                                       <0 6 0x1 0x1    /* PA6 periph A with pullup */
+                                                        0 5 0x1 0x0>;  /* PA5 periph A */
+                                       };
+                               };
+
+                               usart2 {
+                                       pinctrl_usart2: usart2-0 {
+                                               atmel,pins =
+                                                       <0 8 0x1 0x1    /* PA8 periph A with pullup */
+                                                        0 7 0x1 0x0>;  /* PA7 periph A */
+                                       };
+
+                                       pinctrl_usart2_rts: usart2_rts-0 {
+                                               atmel,pins =
+                                                       <1 0 0x2 0x0>;  /* PB0 periph B */
+                                       };
+
+                                       pinctrl_usart2_cts: usart2_cts-0 {
+                                               atmel,pins =
+                                                       <1 1 0x2 0x0>;  /* PB1 periph B */
+                                       };
+                               };
+
+                               usart3 {
+                                       pinctrl_usart3: usart3-0 {
+                                               atmel,pins =
+                                                       <2 23 0x2 0x1   /* PC23 periph B with pullup */
+                                                        2 22 0x2 0x0>; /* PC22 periph B */
+                                       };
+
+                                       pinctrl_usart3_rts: usart3_rts-0 {
+                                               atmel,pins =
+                                                       <2 24 0x2 0x0>; /* PC24 periph B */
+                                       };
+
+                                       pinctrl_usart3_cts: usart3_cts-0 {
+                                               atmel,pins =
+                                                       <2 25 0x2 0x0>; /* PC25 periph B */
+                                       };
+                               };
+
+                               uart0 {
+                                       pinctrl_uart0: uart0-0 {
+                                               atmel,pins =
+                                                       <2 9 0x3 0x1    /* PC9 periph C with pullup */
+                                                        2 8 0x3 0x0>;  /* PC8 periph C */
+                                       };
+                               };
+
+                               uart1 {
+                                       pinctrl_uart1: uart1-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 */
+                                       };
+                               };
+
+                               mmc0 {
+                                       pinctrl_mmc0_slot0_clk_cmd_dat0: mmc0_slot0_clk_cmd_dat0-0 {
+                                               atmel,pins =
+                                                       <0 17 0x1 0x0   /* PA17 periph A */
+                                                        0 16 0x1 0x1   /* PA16 periph A with pullup */
+                                                        0 15 0x1 0x1>; /* PA15 periph A with pullup */
+                                       };
+
+                                       pinctrl_mmc0_slot0_dat1_3: mmc0_slot0_dat1_3-0 {
+                                               atmel,pins =
+                                                       <0 18 0x1 0x1   /* PA18 periph A with pullup */
+                                                        0 19 0x1 0x1   /* PA19 periph A with pullup */
+                                                        0 20 0x1 0x1>; /* PA20 periph A with pullup */
+                                       };
+
+                                       pinctrl_mmc0_slot0_dat4_7: mmc0_slot0_dat4_7-0 {
+                                               atmel,pins =
+                                                       <0 11 0x2 0x1   /* PA11 periph B with pullup */
+                                                        0 12 0x2 0x1   /* PA12 periph B with pullup */
+                                                        0 13 0x2 0x1   /* PA13 periph B with pullup */
+                                                        0 14 0x2 0x1>; /* PA14 periph B with pullup */
+                                       };
+                               };
+
+                               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_usart0>;
                                status = "disabled";
                        };
 
                                interrupts = <6 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_usart1>;
                                status = "disabled";
                        };
 
                                interrupts = <7 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_usart2>;
                                status = "disabled";
                        };
 
                                interrupts = <8 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_usart3>;
                                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
index 912b2c2..0376bf4 100644 (file)
                        i2c1: i2c@f8014000 {
                                status = "okay";
                        };
+
+                       mmc0: mmc@f0008000 {
+                               pinctrl-0 = <
+                                       &pinctrl_board_mmc0
+                                       &pinctrl_mmc0_slot0_clk_cmd_dat0
+                                       &pinctrl_mmc0_slot0_dat1_3>;
+                               status = "okay";
+                               slot@0 {
+                                       reg = <0>;
+                                       bus-width = <4>;
+                                       cd-gpios = <&pioA 7 0>;
+                               };
+                       };
+
+                       pinctrl@fffff400 {
+                               mmc0 {
+                                       pinctrl_board_mmc0: mmc0-board {
+                                               atmel,pins =
+                                                       <0 7 0x0 0x5>;  /* PA7 gpio CD pin pull up and deglitch */
+                                       };
+                               };
+                       };
                };
 
                nand0: nand@40000000 {
diff --git a/arch/arm/boot/dts/at91sam9x25.dtsi b/arch/arm/boot/dts/at91sam9x25.dtsi
new file mode 100644 (file)
index 0000000..54eb33b
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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 */
+                                     >;
+
+                               macb1 {
+                                       pinctrl_macb1_rmii: macb1_rmii-0 {
+                                               atmel,pins =
+                                                       <2 16 0x2 0x0   /* PC16 periph B */
+                                                        2 18 0x2 0x0   /* PC18 periph B */
+                                                        2 19 0x2 0x0   /* PC19 periph B */
+                                                        2 20 0x2 0x0   /* PC20 periph B */
+                                                        2 21 0x2 0x0   /* PC21 periph B */
+                                                        2 27 0x2 0x0   /* PC27 periph B */
+                                                        2 28 0x2 0x0   /* PC28 periph B */
+                                                        2 29 0x2 0x0   /* PC29 periph B */
+                                                        2 30 0x2 0x0   /* PC30 periph B */
+                                                        2 31 0x2 0x0>; /* PC31 periph B */
+                                       };
+                               };
+                       };
+
+                       macb1: ethernet@f8030000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_macb1_rmii>;
+                       };
+               };
+       };
+};
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 03fc136..7ee49e8 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>;
+                               usart0 {
+                                       pinctrl_usart0: usart0-0 {
+                                               atmel,pins =
+                                                       <0 0 0x1 0x1    /* PA0 periph A with pullup */
+                                                        0 1 0x1 0x0>;  /* PA1 periph A */
+                                       };
+
+                                       pinctrl_usart0_rts: usart0_rts-0 {
+                                               atmel,pins =
+                                                       <0 2 0x1 0x0>;  /* PA2 periph A */
+                                       };
+
+                                       pinctrl_usart0_cts: usart0_cts-0 {
+                                               atmel,pins =
+                                                       <0 3 0x1 0x0>;  /* PA3 periph A */
+                                       };
+                               };
+
+                               usart1 {
+                                       pinctrl_usart1: usart1-0 {
+                                               atmel,pins =
+                                                       <0 5 0x1 0x1    /* PA5 periph A with pullup */
+                                                        0 6 0x1 0x0>;  /* PA6 periph A */
+                                       };
+
+                                       pinctrl_usart1_rts: usart1_rts-0 {
+                                               atmel,pins =
+                                                       <3 27 0x3 0x0>; /* PC27 periph C */
+                                       };
+
+                                       pinctrl_usart1_cts: usart1_cts-0 {
+                                               atmel,pins =
+                                                       <3 28 0x3 0x0>; /* PC28 periph C */
+                                       };
+                               };
+
+                               usart2 {
+                                       pinctrl_usart2: usart2-0 {
+                                               atmel,pins =
+                                                       <0 7 0x1 0x1    /* PA7 periph A with pullup */
+                                                        0 8 0x1 0x0>;  /* PA8 periph A */
+                                       };
+
+                                       pinctrl_uart2_rts: uart2_rts-0 {
+                                               atmel,pins =
+                                                       <0 0 0x2 0x0>;  /* PB0 periph B */
+                                       };
+
+                                       pinctrl_uart2_cts: uart2_cts-0 {
+                                               atmel,pins =
+                                                       <0 1 0x2 0x0>;  /* PB1 periph B */
+                                       };
+                               };
+
+                               usart3 {
+                                       pinctrl_uart3: usart3-0 {
+                                               atmel,pins =
+                                                       <3 23 0x2 0x1   /* PC22 periph B with pullup */
+                                                        3 23 0x2 0x0>; /* PC23 periph B */
+                                       };
+
+                                       pinctrl_usart3_rts: usart3_rts-0 {
+                                               atmel,pins =
+                                                       <3 24 0x2 0x0>; /* PC24 periph B */
+                                       };
+
+                                       pinctrl_usart3_cts: usart3_cts-0 {
+                                               atmel,pins =
+                                                       <3 25 0x2 0x0>; /* PC25 periph B */
+                                       };
+                               };
+
+                               uart0 {
+                                       pinctrl_uart0: uart0-0 {
+                                               atmel,pins =
+                                                       <3 8 0x3 0x0    /* PC8 periph C */
+                                                        3 9 0x3 0x1>;  /* PC9 periph C with pullup */
+                                       };
+                               };
+
+                               uart1 {
+                                       pinctrl_uart1: uart1-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 */
+                                       };
+                               };
+
+                               macb0 {
+                                       pinctrl_macb0_rmii: macb0_rmii-0 {
+                                               atmel,pins =
+                                                       <1 0 0x1 0x0    /* PB0 periph A */
+                                                        1 1 0x1 0x0    /* PB1 periph A */
+                                                        1 2 0x1 0x0    /* PB2 periph A */
+                                                        1 3 0x1 0x0    /* PB3 periph A */
+                                                        1 4 0x1 0x0    /* PB4 periph A */
+                                                        1 5 0x1 0x0    /* PB5 periph A */
+                                                        1 6 0x1 0x0    /* PB6 periph A */
+                                                        1 7 0x1 0x0    /* PB7 periph A */
+                                                        1 9 0x1 0x0    /* PB9 periph A */
+                                                        1 10 0x1 0x0>; /* PB10 periph A */
+                                       };
+
+                                       pinctrl_macb0_rmii_mii: macb0_rmii_mii-0 {
+                                               atmel,pins =
+                                                       <1 8 0x1 0x0    /* PA8 periph A */
+                                                        1 11 0x1 0x0   /* PA11 periph A */
+                                                        1 12 0x1 0x0   /* PA12 periph A */
+                                                        1 13 0x1 0x0   /* PA13 periph A */
+                                                        1 14 0x1 0x0   /* PA14 periph A */
+                                                        1 15 0x1 0x0   /* PA15 periph A */
+                                                        1 16 0x1 0x0   /* PA16 periph A */
+                                                        1 17 0x1 0x0>; /* PA17 periph A */
+                                       };
+                               };
+
+                               mmc0 {
+                                       pinctrl_mmc0_slot0_clk_cmd_dat0: mmc0_slot0_clk_cmd_dat0-0 {
+                                               atmel,pins =
+                                                       <0 17 0x1 0x0   /* PA17 periph A */
+                                                        0 16 0x1 0x1   /* PA16 periph A with pullup */
+                                                        0 15 0x1 0x1>; /* PA15 periph A with pullup */
+                                       };
+
+                                       pinctrl_mmc0_slot0_dat1_3: mmc0_slot0_dat1_3-0 {
+                                               atmel,pins =
+                                                       <0 18 0x1 0x1   /* PA18 periph A with pullup */
+                                                        0 19 0x1 0x1   /* PA19 periph A with pullup */
+                                                        0 20 0x1 0x1>; /* PA20 periph A with pullup */
+                                       };
+                               };
+
+                               mmc1 {
+                                       pinctrl_mmc1_slot0_clk_cmd_dat0: mmc1_slot0_clk_cmd_dat0-0 {
+                                               atmel,pins =
+                                                       <0 13 0x2 0x0   /* PA13 periph B */
+                                                        0 12 0x2 0x1   /* PA12 periph B with pullup */
+                                                        0 11 0x2 0x1>; /* PA11 periph B with pullup */
+                                       };
+
+                                       pinctrl_mmc1_slot0_dat1_3: mmc1_slot0_dat1_3-0 {
+                                               atmel,pins =
+                                                       <0 2 0x2 0x1    /* PA2 periph B with pullup */
+                                                        0 3 0x2 0x1    /* PA3 periph B with pullup */
+                                                        0 4 0x2 0x1>;  /* PA4 periph B with pullup */
+                                       };
+                               };
+
+                               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>;
+                               };
                        };
 
-                       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>;
+                       mmc0: mmc@f0008000 {
+                               compatible = "atmel,hsmci";
+                               reg = <0xf0008000 0x600>;
+                               interrupts = <12 4 0>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
                        };
 
-                       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>;
+                       mmc1: mmc@f000c000 {
+                               compatible = "atmel,hsmci";
+                               reg = <0xf000c000 0x600>;
+                               interrupts = <26 4 0>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
                        };
 
                        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_usart0>;
                                status = "disabled";
                        };
 
                                interrupts = <6 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_usart1>;
                                status = "disabled";
                        };
 
                                interrupts = <7 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_usart2>;
                                status = "disabled";
                        };
 
                                compatible = "cdns,at32ap7000-macb", "cdns,macb";
                                reg = <0xf802c000 0x100>;
                                interrupts = <24 4 3>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_macb0_rmii>;
                                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..8a7cf1d
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * 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 {
+                       mmc0: mmc@f0008000 {
+                               pinctrl-0 = <
+                                       &pinctrl_board_mmc0
+                                       &pinctrl_mmc0_slot0_clk_cmd_dat0
+                                       &pinctrl_mmc0_slot0_dat1_3>;
+                               status = "okay";
+                               slot@0 {
+                                       reg = <0>;
+                                       bus-width = <4>;
+                                       cd-gpios = <&pioD 15 0>;
+                               };
+                       };
+
+                       mmc1: mmc@f000c000 {
+                               pinctrl-0 = <
+                                       &pinctrl_board_mmc1
+                                       &pinctrl_mmc1_slot0_clk_cmd_dat0
+                                       &pinctrl_mmc1_slot0_dat1_3>;
+                               status = "okay";
+                               slot@0 {
+                                       reg = <0>;
+                                       bus-width = <4>;
+                                       cd-gpios = <&pioD 14 0>;
+                               };
+                       };
+
+                       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";
+                       };
+
+                       pinctrl@fffff400 {
+                               mmc0 {
+                                       pinctrl_board_mmc0: mmc0-board {
+                                               atmel,pins =
+                                                       <3 15 0x0 0x5>; /* PD15 gpio CD pin pull up and deglitch */
+                                       };
+                               };
+
+                               mmc1 {
+                                       pinctrl_board_mmc1: mmc1-board {
+                                               atmel,pins =
+                                                       <3 14 0x0 0x5>; /* PD14 gpio CD pin pull up and deglitch */
+                                       };
+                               };
+                       };
+               };
+
+               usb0: ohci@00600000 {
+                       status = "okay";
+                       num-ports = <2>;
+                       atmel,vbus-gpio = <&pioD 19 1
+                                          &pioD 20 1
+                                         >;
+               };
+
+               usb1: ehci@00700000 {
+                       status = "okay";
+               };
+       };
+};
index 748ba7a..4b0e0ca 100644 (file)
                        compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
                        reg = <0x80004000 0x1000>;
                        interrupts = <0 21 0x4>;
+                       arm,primecell-periphid = <0x180024>;
+
                        #address-cells = <1>;
                        #size-cells = <0>;
                        v-i2c-supply = <&db8500_vape_reg>;
                        compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
                        reg = <0x80122000 0x1000>;
                        interrupts = <0 22 0x4>;
+                       arm,primecell-periphid = <0x180024>;
+
                        #address-cells = <1>;
                        #size-cells = <0>;
                        v-i2c-supply = <&db8500_vape_reg>;
                        compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
                        reg = <0x80128000 0x1000>;
                        interrupts = <0 55 0x4>;
+                       arm,primecell-periphid = <0x180024>;
+
                        #address-cells = <1>;
                        #size-cells = <0>;
                        v-i2c-supply = <&db8500_vape_reg>;
                        compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
                        reg = <0x80110000 0x1000>;
                        interrupts = <0 12 0x4>;
+                       arm,primecell-periphid = <0x180024>;
+
                        #address-cells = <1>;
                        #size-cells = <0>;
                        v-i2c-supply = <&db8500_vape_reg>;
                        compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
                        reg = <0x8012a000 0x1000>;
                        interrupts = <0 51 0x4>;
+                       arm,primecell-periphid = <0x180024>;
+
                        #address-cells = <1>;
                        #size-cells = <0>;
                        v-i2c-supply = <&db8500_vape_reg>;
                        interrupts = <0 60 0x4>;
                        status = "disabled";
                };
+
                sdi@80118000 {
                        compatible = "arm,pl18x", "arm,primecell";
                        reg = <0x80118000 0x1000>;
                        interrupts = <0 50 0x4>;
                        status = "disabled";
                };
+
                sdi@80005000 {
                        compatible = "arm,pl18x", "arm,primecell";
                        reg = <0x80005000 0x1000>;
                        interrupts = <0 41 0x4>;
                        status = "disabled";
                };
+
                sdi@80119000 {
                        compatible = "arm,pl18x", "arm,primecell";
                        reg = <0x80119000 0x1000>;
                        interrupts = <0 59 0x4>;
                        status = "disabled";
                };
+
                sdi@80114000 {
                        compatible = "arm,pl18x", "arm,primecell";
                        reg = <0x80114000 0x1000>;
                        interrupts = <0 99 0x4>;
                        status = "disabled";
                };
+
                sdi@80008000 {
                        compatible = "arm,pl18x", "arm,primecell";
-                       reg = <0x80114000 0x1000>;
+                       reg = <0x80008000 0x1000>;
                        interrupts = <0 100 0x4>;
                        status = "disabled";
                };
index 96fb824..5a00022 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 73567b8..a21511c 100644 (file)
        compatible = "samsung,trats", "samsung,exynos4210";
 
        memory {
-               reg =  <0x40000000 0x20000000
-                       0x60000000 0x20000000>;
+               reg =  <0x40000000 0x10000000
+                       0x50000000 0x10000000
+                       0x60000000 0x10000000
+                       0x70000000 0x10000000>;
        };
 
        chosen {
index 9ca4ca7..6d31aa3 100644 (file)
@@ -69,6 +69,7 @@
                                interrupts = <13>, <56>;
                                interrupt-names = "gpmi-dma", "bch";
                                clocks = <&clks 34>;
+                               clock-names = "gpmi_io";
                                fsl,gpmi-dma-channel = <4>;
                                status = "disabled";
                        };
index e16d631..55c57ea 100644 (file)
@@ -85,6 +85,7 @@
                                interrupts = <88>, <41>;
                                interrupt-names = "gpmi-dma", "bch";
                                clocks = <&clks 50>;
+                               clock-names = "gpmi_io";
                                fsl,gpmi-dma-channel = <4>;
                                status = "disabled";
                        };
index 15df4c1..5bfa02a 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 8ac51c0..8fea375 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>;
                };
        };
index f38ea87..696e929 100644 (file)
                        interrupt-names = "common", "tx", "rx", "sidetone";
                        interrupt-parent = <&intc>;
                        ti,buffer-size = <1280>;
-                       ti,hwmods = "mcbsp2";
+                       ti,hwmods = "mcbsp2", "mcbsp2_sidetone";
                };
 
                mcbsp3: mcbsp@49024000 {
                        interrupt-names = "common", "tx", "rx", "sidetone";
                        interrupt-parent = <&intc>;
                        ti,buffer-size = <128>;
-                       ti,hwmods = "mcbsp3";
+                       ti,hwmods = "mcbsp3", "mcbsp3_sidetone";
                };
 
                mcbsp4: mcbsp@49026000 {
diff --git a/arch/arm/boot/dts/pm9g45.dts b/arch/arm/boot/dts/pm9g45.dts
new file mode 100644 (file)
index 0000000..387fedb
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * pm9g45.dts - Device Tree file for Ronetix pm9g45 board
+ *
+ *  Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Licensed under GPLv2.
+ */
+/dts-v1/;
+/include/ "at91sam9g45.dtsi"
+
+/ {
+       model = "Ronetix pm9g45";
+       compatible = "ronetix,pm9g45", "atmel,at91sam9g45", "atmel,at91sam9";
+
+       chosen {
+               bootargs = "console=ttyS0,115200";
+       };
+
+       memory {
+               reg = <0x70000000 0x8000000>;
+       };
+
+       clocks {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               main_clock: clock@0 {
+                       compatible = "atmel,osc", "fixed-clock";
+                       clock-frequency = <12000000>;
+               };
+       };
+
+       ahb {
+               apb {
+                       dbgu: serial@ffffee00 {
+                               status = "okay";
+                       };
+
+                       pinctrl@fffff200 {
+
+                               board {
+                                       pinctrl_board_nand: nand0-board {
+                                               atmel,pins =
+                                                       <3 3 0x0 0x1    /* PD3 gpio RDY pin pull_up*/
+                                                        2 14 0x0 0x1>; /* PC14 gpio enable pin pull_up */
+                                       };
+                               };
+
+                               mmc {
+                                       pinctrl_board_mmc: mmc0-board {
+                                               atmel,pins =
+                                                       <3 6 0x0 0x5>;  /* PD6 gpio CD pin pull_up and deglitch */
+                                       };
+                               };
+                       };
+
+                       mmc0: mmc@fff80000 {
+                               pinctrl-0 = <
+                                       &pinctrl_board_mmc
+                                       &pinctrl_mmc0_slot0_clk_cmd_dat0
+                                       &pinctrl_mmc0_slot0_dat1_3>;
+                               status = "okay";
+                               slot@0 {
+                                       reg = <0>;
+                                       bus-width = <4>;
+                                       cd-gpios = <&pioD 6 0>;
+                               };
+                       };
+
+                       macb0: ethernet@fffbc000 {
+                               phy-mode = "rmii";
+                               status = "okay";
+                       };
+
+               };
+
+               nand0: nand@40000000 {
+                       nand-bus-width = <8>;
+                       nand-ecc-mode = "soft";
+                       nand-on-flash-bbt;
+                       pinctrl-0 = <&pinctrl_board_nand>;
+
+                       gpios = <&pioD 3 0
+                                &pioC 14 0
+                                0
+                               >;
+
+                       status = "okay";
+
+                       at91bootstrap@0 {
+                               label = "at91bootstrap";
+                               reg = <0x0 0x20000>;
+                       };
+
+                       barebox@20000 {
+                               label = "barebox";
+                               reg = <0x20000 0x40000>;
+                       };
+
+                       bareboxenv@60000 {
+                               label = "bareboxenv";
+                               reg = <0x60000 0x1A0000>;
+                       };
+
+                       kernel@200000 {
+                               label = "bareboxenv2";
+                               reg = <0x200000 0x300000>;
+                       };
+
+                       kernel@500000 {
+                               label = "root";
+                               reg = <0x500000 0x400000>;
+                       };
+
+                       data@900000 {
+                               label = "data";
+                               reg = <0x900000 0x8340000>;
+                       };
+               };
+
+               usb0: ohci@00700000 {
+                       status = "okay";
+                       num-ports = <2>;
+               };
+
+               usb1: ehci@00800000 {
+                       status = "okay";
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               led0 {
+                       label = "led0";
+                       gpios = <&pioD 0 1>;
+                       linux,default-trigger = "nand-disk";
+               };
+
+               led1 {
+                       label = "led1";
+                       gpios = <&pioD 31 0>;
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+
+       gpio_keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               right {
+                       label = "SW4";
+                       gpios = <&pioE 7 1>;
+                       linux,code = <106>;
+               };
+
+               up {
+                       label = "SW3";
+                       gpios = <&pioE 8 1>;
+                       linux,code = <103>;
+               };
+       };
+};
index dd4358b..2e4c572 100644 (file)
                               status = "okay";
                        };
 
+                       gpio@d8400000 {
+                              status = "okay";
+                       };
+
                        i2c0: i2c@e0280000 {
                               status = "okay";
                        };
index 419ea74..7cd25eb 100644 (file)
                        status = "disabled";
                };
 
+               pinmux: pinmux@e0700000 {
+                       compatible = "st,spear1310-pinmux";
+                       reg = <0xe0700000 0x1000>;
+                       #gpio-range-cells = <2>;
+               };
+
                spi1: spi@5d400000 {
                        compatible = "arm,pl022", "arm,primecell";
                        reg = <0x5d400000 0x1000>;
                        thermal@e07008c4 {
                                st,thermal-flags = <0x7000>;
                        };
+
+                       gpiopinctrl: gpio@d8400000 {
+                               compatible = "st,spear-plgpio";
+                               reg = <0xd8400000 0x1000>;
+                               interrupts = <0 100 0x4>;
+                               #interrupt-cells = <1>;
+                               interrupt-controller;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               gpio-ranges = <&pinmux 0 246>;
+                               status = "disabled";
+
+                               st-plgpio,ngpio = <246>;
+                               st-plgpio,enb-reg = <0xd0>;
+                               st-plgpio,wdata-reg = <0x90>;
+                               st-plgpio,dir-reg = <0xb0>;
+                               st-plgpio,ie-reg = <0x30>;
+                               st-plgpio,rdata-reg = <0x70>;
+                               st-plgpio,mis-reg = <0x10>;
+                               st-plgpio,eit-reg = <0x50>;
+                       };
                };
        };
 };
index c9a54e0..045f712 100644 (file)
                               status = "okay";
                        };
 
+                       gpio@e2800000 {
+                              status = "okay";
+                       };
+
                        i2c0: i2c@e0280000 {
                               status = "okay";
                        };
index d71fe2a..6c09eb0 100644 (file)
                        status = "disabled";
                };
 
+               pinmux: pinmux@e0700000 {
+                       compatible = "st,spear1340-pinmux";
+                       reg = <0xe0700000 0x1000>;
+                       #gpio-range-cells = <2>;
+               };
+
                spi1: spi@5d400000 {
                        compatible = "arm,pl022", "arm,primecell";
                        reg = <0x5d400000 0x1000>;
                        thermal@e07008c4 {
                                st,thermal-flags = <0x2a00>;
                        };
+
+                       gpiopinctrl: gpio@e2800000 {
+                               compatible = "st,spear-plgpio";
+                               reg = <0xe2800000 0x1000>;
+                               interrupts = <0 107 0x4>;
+                               #interrupt-cells = <1>;
+                               interrupt-controller;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               gpio-ranges = <&pinmux 0 252>;
+                               status = "disabled";
+
+                               st-plgpio,ngpio = <250>;
+                               st-plgpio,wdata-reg = <0x40>;
+                               st-plgpio,dir-reg = <0x00>;
+                               st-plgpio,ie-reg = <0x80>;
+                               st-plgpio,rdata-reg = <0x20>;
+                               st-plgpio,mis-reg = <0xa0>;
+                               st-plgpio,eit-reg = <0x60>;
+                       };
                };
        };
 };
index 62fc4fb..930303e 100644 (file)
                          0xb0000000 0xb0000000 0x10000000
                          0xd0000000 0xd0000000 0x30000000>;
 
-               pinmux@b4000000 {
+               pinmux: pinmux@b4000000 {
                        compatible = "st,spear310-pinmux";
                        reg = <0xb4000000 0x1000>;
+                       #gpio-range-cells = <2>;
                };
 
                fsmc: flash@44000000 {
                                reg = <0xb2200000 0x1000>;
                                status = "disabled";
                        };
+
+                       gpiopinctrl: gpio@b4000000 {
+                               compatible = "st,spear-plgpio";
+                               reg = <0xb4000000 0x1000>;
+                               #interrupt-cells = <1>;
+                               interrupt-controller;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               gpio-ranges = <&pinmux 0 102>;
+                               status = "disabled";
+
+                               st-plgpio,ngpio = <102>;
+                               st-plgpio,enb-reg = <0x10>;
+                               st-plgpio,wdata-reg = <0x20>;
+                               st-plgpio,dir-reg = <0x30>;
+                               st-plgpio,ie-reg = <0x50>;
+                               st-plgpio,rdata-reg = <0x40>;
+                               st-plgpio,mis-reg = <0x60>;
+                       };
                };
        };
 };
index 082328b..ad4bfc6 100644 (file)
                               status = "okay";
                        };
 
+                       gpio@b3000000 {
+                              status = "okay";
+                       };
+
                        i2c0: i2c@d0180000 {
                               status = "okay";
                        };
index 1f49d69..67d7ada 100644 (file)
                ranges = <0x40000000 0x40000000 0x80000000
                          0xd0000000 0xd0000000 0x30000000>;
 
-               pinmux@b3000000 {
+               pinmux: pinmux@b3000000 {
                        compatible = "st,spear320-pinmux";
                        reg = <0xb3000000 0x1000>;
+                       #gpio-range-cells = <2>;
                };
 
                clcd@90000000 {
                                reg = <0xa4000000 0x1000>;
                                status = "disabled";
                        };
+
+                       gpiopinctrl: gpio@b3000000 {
+                               compatible = "st,spear-plgpio";
+                               reg = <0xb3000000 0x1000>;
+                               #interrupt-cells = <1>;
+                               interrupt-controller;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               gpio-ranges = <&pinmux 0 102>;
+                               status = "disabled";
+
+                               st-plgpio,ngpio = <102>;
+                               st-plgpio,enb-reg = <0x24>;
+                               st-plgpio,wdata-reg = <0x34>;
+                               st-plgpio,dir-reg = <0x44>;
+                               st-plgpio,ie-reg = <0x64>;
+                               st-plgpio,rdata-reg = <0x54>;
+                               st-plgpio,mis-reg = <0x84>;
+                               st-plgpio,eit-reg = <0x94>;
+                       };
                };
        };
 };
index f0ba901..a20d4ff 100644 (file)
                };
 
                temperature-sensor@4c {
-                       compatible = "nct1008";
+                       compatible = "onnn,nct1008";
                        reg = <0x4c>;
                };
 
                magnetometer@c {
-                       compatible = "ak8975";
+                       compatible = "ak,ak8975";
                        reg = <0xc>;
                        interrupt-parent = <&gpio>;
                        interrupts = <109 0x04>; /* gpio PN5 */
index b1497c7..df7f227 100644 (file)
@@ -73,8 +73,8 @@
 
        pinmux: pinmux {
                compatible = "nvidia,tegra30-pinmux";
-               reg = <0x70000868 0xd0    /* Pad control registers */
-                      0x70003000 0x3e0>; /* Mux registers */
+               reg = <0x70000868 0xd4    /* Pad control registers */
+                      0x70003000 0x3e4>; /* Mux registers */
        };
 
        serial@70006000 {
index b459691..330f833 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 df13a3f..9d2d3ba 100644 (file)
@@ -162,7 +162,6 @@ static struct clock_event_device sp804_clockevent = {
        .set_mode       = sp804_set_mode,
        .set_next_event = sp804_set_next_event,
        .rating         = 300,
-       .cpumask        = cpu_all_mask,
 };
 
 static struct irqaction sp804_timer_irq = {
@@ -185,6 +184,7 @@ void __init sp804_clockevents_init(void __iomem *base, unsigned int irq,
        clkevt_reload = DIV_ROUND_CLOSEST(rate, HZ);
        evt->name = name;
        evt->irq = irq;
+       evt->cpumask = cpu_possible_mask;
 
        setup_irq(irq, &sp804_timer_irq);
        clockevents_config_and_register(evt, rate, 0xf, 0xffffffff);
index 67bc571..b175577 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 66aa7a6..394ded6 100644 (file)
@@ -139,6 +139,7 @@ CONFIG_I2C_IMX=y
 CONFIG_SPI=y
 CONFIG_SPI_IMX=y
 CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_MC9S08DZ60=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_IMX2_WDT=y
@@ -155,6 +156,7 @@ CONFIG_SOC_CAMERA=y
 CONFIG_SOC_CAMERA_OV2640=y
 CONFIG_VIDEO_MX3=y
 CONFIG_FB=y
+CONFIG_LCD_PLATFORM=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=y
 CONFIG_LCD_L4F00242T03=y
index 7bcf850..3458752 100644 (file)
@@ -1,6 +1,6 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
-CONFIG_NO_HZ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
@@ -9,10 +9,12 @@ CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_MVEBU=y
-CONFIG_MACH_ARMADA_370_XP=y
+CONFIG_MACH_ARMADA_370=y
+CONFIG_MACH_ARMADA_XP=y
+# CONFIG_CACHE_L2X0 is not set
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
-CONFIG_USE_OF=y
+# CONFIG_COMPACTION is not set
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_ARM_APPENDED_DTB=y
@@ -23,6 +25,8 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_SYSFS=y
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_FS_XATTR is not set
index cdd4d2b..2ba9e63 100644 (file)
@@ -1,3 +1,4 @@
+CONFIG_ARCH_VERSATILE=y
 CONFIG_EXPERIMENTAL=y
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SYSVIPC=y
index 59426a4..e847d23 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 6b9b077..afd7e91 100644 (file)
@@ -56,6 +56,8 @@
 #define SCCTRL_TIMEREN1SEL_REFCLK      (0 << 17)
 #define SCCTRL_TIMEREN1SEL_TIMCLK      (1 << 17)
 
+#define SCCTRL_TIMERENnSEL_SHIFT(n)    (15 + ((n) * 2))
+
 static inline void sysctl_soft_reset(void __iomem *base)
 {
        /* switch to slow mode */
index 35c1ed8..42f042e 100644 (file)
@@ -64,7 +64,7 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
 static inline void __raw_writew(u16 val, volatile void __iomem *addr)
 {
        asm volatile("strh %1, %0"
-                    : "+Qo" (*(volatile u16 __force *)addr)
+                    : "+Q" (*(volatile u16 __force *)addr)
                     : "r" (val));
 }
 
@@ -72,7 +72,7 @@ static inline u16 __raw_readw(const volatile void __iomem *addr)
 {
        u16 val;
        asm volatile("ldrh %1, %0"
-                    : "+Qo" (*(volatile u16 __force *)addr),
+                    : "+Q" (*(volatile u16 __force *)addr),
                       "=r" (val));
        return val;
 }
index aeae9c6..6d65ba2 100644 (file)
@@ -11,6 +11,8 @@
 #ifndef __ASMARM_PROM_H
 #define __ASMARM_PROM_H
 
+#define HAVE_ARCH_DEVTREE_FIXUPS
+
 #ifdef CONFIG_OF
 
 extern struct machine_desc *setup_machine_fdt(unsigned int dt_phys);
index 05b8e82..e3f7572 100644 (file)
@@ -10,7 +10,5 @@
 
 extern void sched_clock_postinit(void);
 extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate);
-extern void setup_sched_clock_needs_suspend(u32 (*read)(void), int bits,
-               unsigned long rate);
 
 #endif
index 77bd79f..7e1f760 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 6a6f1e4..301c1db 100644 (file)
@@ -27,9 +27,9 @@
 #if __LINUX_ARM_ARCH__ <= 6
        ldr     \tmp, =elf_hwcap                    @ may not have MVFR regs
        ldr     \tmp, [\tmp, #0]
-       tst     \tmp, #HWCAP_VFPv3D16
-       ldceql  p11, cr0, [\base],#32*4             @ FLDMIAD \base!, {d16-d31}
-       addne   \base, \base, #32*4                 @ step over unused register space
+       tst     \tmp, #HWCAP_VFPD32
+       ldcnel  p11, cr0, [\base],#32*4             @ FLDMIAD \base!, {d16-d31}
+       addeq   \base, \base, #32*4                 @ step over unused register space
 #else
        VFPFMRX \tmp, MVFR0                         @ Media and VFP Feature Register 0
        and     \tmp, \tmp, #MVFR0_A_SIMD_MASK      @ A_SIMD field
@@ -51,9 +51,9 @@
 #if __LINUX_ARM_ARCH__ <= 6
        ldr     \tmp, =elf_hwcap                    @ may not have MVFR regs
        ldr     \tmp, [\tmp, #0]
-       tst     \tmp, #HWCAP_VFPv3D16
-       stceql  p11, cr0, [\base],#32*4             @ FSTMIAD \base!, {d16-d31}
-       addne   \base, \base, #32*4                 @ step over unused register space
+       tst     \tmp, #HWCAP_VFPD32
+       stcnel  p11, cr0, [\base],#32*4             @ FSTMIAD \base!, {d16-d31}
+       addeq   \base, \base, #32*4                 @ step over unused register space
 #else
        VFPFMRX \tmp, MVFR0                         @ Media and VFP Feature Register 0
        and     \tmp, \tmp, #MVFR0_A_SIMD_MASK      @ A_SIMD field
index ae05e56..5000397 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 1742023..c6b9096 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 */
diff --git a/arch/arm/include/debug/8250_32.S b/arch/arm/include/debug/8250_32.S
new file mode 100644 (file)
index 0000000..8db01ee
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * 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.
+ *
+ * Derived from arch/arm/mach-davinci/include/mach/debug-macro.S to use 32-bit
+ * accesses to the 8250.
+ */
+
+#include <linux/serial_reg.h>
+
+               .macro  senduart,rd,rx
+               str     \rd, [\rx, #UART_TX << UART_SHIFT]
+               .endm
+
+               .macro  busyuart,rd,rx
+1002:          ldr     \rd, [\rx, #UART_LSR << UART_SHIFT]
+               and     \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
+               teq     \rd, #UART_LSR_TEMT | UART_LSR_THRE
+               bne     1002b
+               .endm
+
+               /* The UART's don't have any flow control IO's wired up. */
+               .macro  waituart,rd,rx
+               .endm
index 7419deb..bc1f07c 100644 (file)
@@ -5,10 +5,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * Derived from arch/arm/mach-davinci/include/mach/debug-macro.S to use 32-bit
- * accesses to the 8250.
  */
-#include <linux/serial_reg.h>
 
 #define UART_SHIFT 2
 #define PICOXCELL_UART1_BASE           0x80230000
                ldr     \rp, =PICOXCELL_UART1_BASE
                .endm
 
-               .macro  senduart,rd,rx
-               str     \rd, [\rx, #UART_TX << UART_SHIFT]
-               .endm
-
-               .macro  busyuart,rd,rx
-1002:          ldr     \rd, [\rx, #UART_LSR << UART_SHIFT]
-               and     \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
-               teq     \rd, #UART_LSR_TEMT | UART_LSR_THRE
-               bne     1002b
-               .endm
-
-               /* The UART's don't have any flow control IO's wired up. */
-               .macro  waituart,rd,rx
-               .endm
+#include "8250_32.S"
index d6f26d2..966b2f9 100644 (file)
@@ -7,6 +7,9 @@
  * published by the Free Software Foundation.
  */
 
+#define UART_SHIFT 2
+#define DEBUG_LL_UART_OFFSET   0x00002000
+
                .macro  addruart, rp, rv, tmp
                mov     \rp, #DEBUG_LL_UART_OFFSET
                orr     \rp, \rp, #0x00c00000
@@ -14,3 +17,5 @@
                orr     \rp, \rp, #0xff000000   @ physical base
                .endm
 
+#include "8250_32.S"
+
index f254f65..3688fd1 100644 (file)
 #define HWCAP_THUMBEE  (1 << 11)
 #define HWCAP_NEON     (1 << 12)
 #define HWCAP_VFPv3    (1 << 13)
-#define HWCAP_VFPv3D16 (1 << 14)
+#define HWCAP_VFPv3D16 (1 << 14)       /* also set for VFPv4-D16 */
 #define HWCAP_TLS      (1 << 15)
 #define HWCAP_VFPv4    (1 << 16)
 #define HWCAP_IDIVA    (1 << 17)
 #define HWCAP_IDIVT    (1 << 18)
+#define HWCAP_VFPD32   (1 << 19)       /* set if VFP has 32 regs (not 16) */
 #define HWCAP_IDIV     (HWCAP_IDIVA | HWCAP_IDIVT)
 
 
index 417bac1..3471175 100644 (file)
@@ -88,9 +88,9 @@ ENTRY(ret_from_fork)
        bl      schedule_tail
        cmp     r5, #0
        movne   r0, r4
-       movne   lr, pc
+       adrne   lr, BSYM(1f)
        movne   pc, r5
-       get_thread_info tsk
+1:     get_thread_info tsk
        b       ret_slow_syscall
 ENDPROC(ret_from_fork)
 
index 16cedb4..8961650 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 38c1a3b..8393129 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 e29c333..8ef8c93 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 93971b1..53c0304 100644 (file)
@@ -96,6 +96,10 @@ armpmu_event_set_period(struct perf_event *event,
        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);
index e21bac2..fc6692e 100644 (file)
@@ -107,13 +107,6 @@ static void sched_clock_poll(unsigned long wrap_ticks)
        update_sched_clock();
 }
 
-void __init setup_sched_clock_needs_suspend(u32 (*read)(void), int bits,
-               unsigned long rate)
-{
-       setup_sched_clock(read, bits, rate);
-       cd.needs_suspend = true;
-}
-
 void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
 {
        unsigned long r, w;
@@ -189,18 +182,15 @@ void __init sched_clock_postinit(void)
 static int sched_clock_suspend(void)
 {
        sched_clock_poll(sched_clock_timer.data);
-       if (cd.needs_suspend)
-               cd.suspended = true;
+       cd.suspended = true;
        return 0;
 }
 
 static void sched_clock_resume(void)
 {
-       if (cd.needs_suspend) {
-               cd.epoch_cyc = read_sched_clock();
-               cd.epoch_cyc_copy = cd.epoch_cyc;
-               cd.suspended = false;
-       }
+       cd.epoch_cyc = read_sched_clock();
+       cd.epoch_cyc_copy = cd.epoch_cyc;
+       cd.suspended = false;
 }
 
 static struct syscore_ops sched_clock_ops = {
index 8e20754..fbc8b26 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 e1f9069..b22d700 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 9d0a300..0dc5385 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 b142071..e34c1bd 100644 (file)
@@ -21,19 +21,13 @@ config SOC_AT91SAM9
        bool
        select CPU_ARM926T
        select GENERIC_CLOCKEVENTS
+       select MULTI_IRQ_HANDLER
+       select SPARSE_IRQ
 
 menu "Atmel AT91 System-on-Chip"
 
 comment "Atmel AT91 Processor"
 
-config SOC_AT91SAM9
-       bool
-       select AT91_SAM9_SMC
-       select AT91_SAM9_TIME
-       select CPU_ARM926T
-       select MULTI_IRQ_HANDLER
-       select SPARSE_IRQ
-
 config SOC_AT91RM9200
        bool "AT91RM9200"
        select CPU_ARM920T
@@ -500,8 +494,17 @@ endif
 
 comment "Generic Board Type"
 
+config MACH_AT91RM9200_DT
+       bool "Atmel AT91RM9200 Evaluation Kits with device-tree support"
+       depends on SOC_AT91RM9200
+       select USE_OF
+       help
+         Select this if you want to experiment device-tree with
+         an Atmel RM9200 Evaluation Kit.
+
 config MACH_AT91SAM_DT
        bool "Atmel AT91SAM Evaluation Kits with device-tree support"
+       depends on SOC_AT91SAM9
        select USE_OF
        help
          Select this if you want to experiment device-tree with
index 3bb7a51..b38a1dc 100644 (file)
@@ -88,6 +88,7 @@ obj-$(CONFIG_MACH_SNAPPER_9260)       += board-snapper9260.o
 obj-$(CONFIG_MACH_AT91SAM9M10G45EK) += board-sam9m10g45ek.o
 
 # AT91SAM board with device-tree
+obj-$(CONFIG_MACH_AT91RM9200_DT) += board-rm9200-dt.o
 obj-$(CONFIG_MACH_AT91SAM_DT) += board-dt.o
 
 # AT91X40 board-specific support
index b4f0565..6cceb42 100644 (file)
@@ -187,13 +187,31 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
        CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
        CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200", &twi_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200.0", &twi_clk),
        /* fake hclk clock */
        CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
        CLKDEV_CON_ID("pioA", &pioA_clk),
        CLKDEV_CON_ID("pioB", &pioB_clk),
        CLKDEV_CON_ID("pioC", &pioC_clk),
        CLKDEV_CON_ID("pioD", &pioD_clk),
+       /* usart lookup table for DT entries */
+       CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
+       CLKDEV_CON_DEV_ID("usart", "fffc0000.serial", &usart0_clk),
+       CLKDEV_CON_DEV_ID("usart", "fffc4000.serial", &usart1_clk),
+       CLKDEV_CON_DEV_ID("usart", "fffc8000.serial", &usart2_clk),
+       CLKDEV_CON_DEV_ID("usart", "fffcc000.serial", &usart3_clk),
+       /* tc lookup table for DT entries */
+       CLKDEV_CON_DEV_ID("t0_clk", "fffa0000.timer", &tc0_clk),
+       CLKDEV_CON_DEV_ID("t1_clk", "fffa0000.timer", &tc1_clk),
+       CLKDEV_CON_DEV_ID("t2_clk", "fffa0000.timer", &tc2_clk),
+       CLKDEV_CON_DEV_ID("t0_clk", "fffa4000.timer", &tc3_clk),
+       CLKDEV_CON_DEV_ID("t1_clk", "fffa4000.timer", &tc4_clk),
+       CLKDEV_CON_DEV_ID("t2_clk", "fffa4000.timer", &tc5_clk),
+       CLKDEV_CON_DEV_ID("hclk", "300000.ohci", &ohci_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),
+       CLKDEV_CON_DEV_ID(NULL, "fffffa00.gpio", &pioD_clk),
 };
 
 static struct clk_lookup usart_clocks_lookups[] = {
@@ -361,10 +379,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 a563189..3cee0e6 100644 (file)
@@ -68,7 +68,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data)
 
        /* Enable overcurrent notification */
        for (i = 0; i < data->ports; i++) {
-               if (data->overcurrent_pin[i])
+               if (gpio_is_valid(data->overcurrent_pin[i]))
                        at91_set_gpio_input(data->overcurrent_pin[i], 1);
        }
 
@@ -479,7 +479,7 @@ static struct i2c_gpio_platform_data pdata = {
 
 static struct platform_device at91rm9200_twi_device = {
        .name                   = "i2c-gpio",
-       .id                     = -1,
+       .id                     = 0,
        .dev.platform_data      = &pdata,
 };
 
@@ -512,7 +512,7 @@ static struct resource twi_resources[] = {
 
 static struct platform_device at91rm9200_twi_device = {
        .name           = "i2c-at91rm9200",
-       .id             = -1,
+       .id             = 0,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
 };
index aaa443b..cafe988 100644 (file)
@@ -24,6 +24,9 @@
 #include <linux/irq.h>
 #include <linux/clockchips.h>
 #include <linux/export.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include <asm/mach/time.h>
 
@@ -91,7 +94,8 @@ static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id)
 static struct irqaction at91rm9200_timer_irq = {
        .name           = "at91_tick",
        .flags          = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-       .handler        = at91rm9200_timer_interrupt
+       .handler        = at91rm9200_timer_interrupt,
+       .irq            = NR_IRQS_LEGACY + AT91_ID_SYS,
 };
 
 static cycle_t read_clk32k(struct clocksource *cs)
@@ -179,8 +183,60 @@ static struct clock_event_device clkevt = {
 void __iomem *at91_st_base;
 EXPORT_SYMBOL_GPL(at91_st_base);
 
+#ifdef CONFIG_OF
+static struct of_device_id at91rm9200_st_timer_ids[] = {
+       { .compatible = "atmel,at91rm9200-st" },
+       { /* sentinel */ }
+};
+
+static int __init of_at91rm9200_st_init(void)
+{
+       struct device_node *np;
+       int ret;
+
+       np = of_find_matching_node(NULL, at91rm9200_st_timer_ids);
+       if (!np)
+               goto err;
+
+       at91_st_base = of_iomap(np, 0);
+       if (!at91_st_base)
+               goto node_err;
+
+       /* Get the interrupts property */
+       ret = irq_of_parse_and_map(np, 0);
+       if (!ret)
+               goto ioremap_err;
+       at91rm9200_timer_irq.irq = ret;
+
+       of_node_put(np);
+
+       return 0;
+
+ioremap_err:
+       iounmap(at91_st_base);
+node_err:
+       of_node_put(np);
+err:
+       return -EINVAL;
+}
+#else
+static int __init of_at91rm9200_st_init(void)
+{
+       return -EINVAL;
+}
+#endif
+
 void __init at91rm9200_ioremap_st(u32 addr)
 {
+#ifdef CONFIG_OF
+       struct device_node *np;
+
+       np = of_find_matching_node(NULL, at91rm9200_st_timer_ids);
+       if (np) {
+               of_node_put(np);
+               return;
+       }
+#endif
        at91_st_base = ioremap(addr, 256);
        if (!at91_st_base)
                panic("Impossible to ioremap ST\n");
@@ -191,13 +247,16 @@ void __init at91rm9200_ioremap_st(u32 addr)
  */
 void __init at91rm9200_timer_init(void)
 {
+       /* For device tree enabled device: initialize here */
+       of_at91rm9200_st_init();
+
        /* Disable all timer interrupts, and clear any pending ones */
        at91_st_write(AT91_ST_IDR,
                AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS);
        at91_st_read(AT91_ST_SR);
 
        /* Make IRQs happen for the system timer */
-       setup_irq(NR_IRQS_LEGACY + AT91_ID_SYS, &at91rm9200_timer_irq);
+       setup_irq(at91rm9200_timer_irq.irq, &at91rm9200_timer_irq);
 
        /* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used
         * directly for the clocksource and all clockevents, after adjusting
index ad29f93..c9e029e 100644 (file)
@@ -211,8 +211,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
        CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
        CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20", &twi_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi_clk),
        /* more usart lookup table for DT entries */
        CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
        CLKDEV_CON_DEV_ID("usart", "fffb0000.serial", &usart0_clk),
@@ -230,11 +230,15 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t1_clk", "fffdc000.timer", &tc4_clk),
        CLKDEV_CON_DEV_ID("t2_clk", "fffdc000.timer", &tc5_clk),
        CLKDEV_CON_DEV_ID("hclk", "500000.ohci", &ohci_clk),
+       CLKDEV_CON_DEV_ID("mci_clk", "fffa8000.mmc", &mmc_clk),
        /* fake hclk clock */
        CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
        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 +394,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 a76b868..414bd85 100644 (file)
@@ -72,7 +72,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data)
 
        /* Enable overcurrent notification */
        for (i = 0; i < data->ports; i++) {
-               if (data->overcurrent_pin[i])
+               if (gpio_is_valid(data->overcurrent_pin[i]))
                        at91_set_gpio_input(data->overcurrent_pin[i], 1);
        }
 
@@ -389,7 +389,7 @@ static struct i2c_gpio_platform_data pdata = {
 
 static struct platform_device at91sam9260_twi_device = {
        .name                   = "i2c-gpio",
-       .id                     = -1,
+       .id                     = 0,
        .dev.platform_data      = &pdata,
 };
 
@@ -421,7 +421,7 @@ static struct resource twi_resources[] = {
 };
 
 static struct platform_device at91sam9260_twi_device = {
-       .id             = -1,
+       .id             = 0,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
 };
index 8d999eb..4d262f3 100644 (file)
@@ -178,8 +178,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
        CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
        CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &hck0),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261", &twi_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10", &twi_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261.0", &twi_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.0", &twi_clk),
        CLKDEV_CON_ID("pioA", &pioA_clk),
        CLKDEV_CON_ID("pioB", &pioB_clk),
        CLKDEV_CON_ID("pioC", &pioC_clk),
@@ -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 9752f17..cd604aa 100644 (file)
@@ -72,7 +72,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data)
 
        /* Enable overcurrent notification */
        for (i = 0; i < data->ports; i++) {
-               if (data->overcurrent_pin[i])
+               if (gpio_is_valid(data->overcurrent_pin[i]))
                        at91_set_gpio_input(data->overcurrent_pin[i], 1);
        }
 
@@ -285,7 +285,7 @@ static struct i2c_gpio_platform_data pdata = {
 
 static struct platform_device at91sam9261_twi_device = {
        .name                   = "i2c-gpio",
-       .id                     = -1,
+       .id                     = 0,
        .dev.platform_data      = &pdata,
 };
 
@@ -317,7 +317,7 @@ static struct resource twi_resources[] = {
 };
 
 static struct platform_device at91sam9261_twi_device = {
-       .id             = -1,
+       .id             = 0,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
 };
index 6a01d03..ed390f6 100644 (file)
@@ -193,7 +193,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
        CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk),
        /* fake hclk clock */
        CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
        CLKDEV_CON_ID("pioA", &pioA_clk),
@@ -211,7 +211,14 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("hclk", "a00000.ohci", &ohci_clk),
        CLKDEV_CON_DEV_ID("spi_clk", "fffa4000.spi", &spi0_clk),
        CLKDEV_CON_DEV_ID("spi_clk", "fffa8000.spi", &spi1_clk),
+       CLKDEV_CON_DEV_ID("mci_clk", "fff80000.mmc", &mmc0_clk),
+       CLKDEV_CON_DEV_ID("mci_clk", "fff84000.mmc", &mmc1_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 +372,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 8dde220..9c61e59 100644 (file)
@@ -78,7 +78,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data)
 
        /* Enable overcurrent notification */
        for (i = 0; i < data->ports; i++) {
-               if (data->overcurrent_pin[i])
+               if (gpio_is_valid(data->overcurrent_pin[i]))
                        at91_set_gpio_input(data->overcurrent_pin[i], 1);
        }
 
@@ -567,7 +567,7 @@ static struct i2c_gpio_platform_data pdata = {
 
 static struct platform_device at91sam9263_twi_device = {
        .name                   = "i2c-gpio",
-       .id                     = -1,
+       .id                     = 0,
        .dev.platform_data      = &pdata,
 };
 
@@ -600,7 +600,7 @@ static struct resource twi_resources[] = {
 
 static struct platform_device at91sam9263_twi_device = {
        .name           = "i2c-at91sam9260",
-       .id             = -1,
+       .id             = 0,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
 };
index 84af1b5..c5c2acc 100644 (file)
@@ -256,10 +256,18 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t0_clk", "fffd4000.timer", &tcb0_clk),
        CLKDEV_CON_DEV_ID("hclk", "700000.ohci", &uhphs_clk),
        CLKDEV_CON_DEV_ID("ehci_clk", "800000.ehci", &uhphs_clk),
+       CLKDEV_CON_DEV_ID("mci_clk", "fff80000.mmc", &mmc0_clk),
+       CLKDEV_CON_DEV_ID("mci_clk", "fffd0000.mmc", &mmc1_clk),
        CLKDEV_CON_DEV_ID(NULL, "fff84000.i2c", &twi0_clk),
        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 +417,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 b159607..fcd233c 100644 (file)
@@ -1841,8 +1841,8 @@ static struct resource sha_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_AESTDESSHA,
-               .end    = AT91SAM9G45_ID_AESTDESSHA,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1874,8 +1874,8 @@ static struct resource tdes_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_AESTDESSHA,
-               .end    = AT91SAM9G45_ID_AESTDESSHA,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1910,8 +1910,8 @@ static struct resource aes_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_AESTDESSHA,
-               .end    = AT91SAM9G45_ID_AESTDESSHA,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
                .flags  = IORESOURCE_IRQ,
        },
 };
index 732d3d3..70b3a99 100644 (file)
@@ -168,13 +168,14 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("usart", "f8028000.serial", &usart3_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb_clk),
+       CLKDEV_CON_DEV_ID("mci_clk", "f0008000.mmc", &mmc_clk),
        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 +224,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 72e9084..cbe72e4 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 d6ca054..5047bdc 100644 (file)
@@ -314,7 +314,7 @@ static struct i2c_gpio_platform_data pdata = {
 
 static struct platform_device at91sam9rl_twi_device = {
        .name                   = "i2c-gpio",
-       .id                     = -1,
+       .id                     = 0,
        .dev.platform_data      = &pdata,
 };
 
@@ -347,7 +347,7 @@ static struct resource twi_resources[] = {
 
 static struct platform_device at91sam9rl_twi_device = {
        .name           = "i2c-at91sam9g20",
-       .id             = -1,
+       .id             = 0,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
 };
index e503538..3c729f0 100644 (file)
@@ -229,15 +229,17 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("usart", "f8028000.serial", &usart3_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb0_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb0_clk),
+       CLKDEV_CON_DEV_ID("mci_clk", "f0008000.mmc", &mmc0_clk),
+       CLKDEV_CON_DEV_ID("mci_clk", "f000c000.mmc", &mmc1_clk),
        CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma0_clk),
        CLKDEV_CON_DEV_ID("dma_clk", "ffffee00.dma-controller", &dma1_clk),
        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 +315,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 6bd7300..bb7f544 100644 (file)
@@ -88,6 +88,6 @@ void __init at91x40_init_interrupts(unsigned int priority[NR_AIC_IRQS])
        if (!priority)
                priority = at91x40_default_irq_priority;
 
-       at91_aic_init(priority);
+       at91_aic_init(priority, at91_extern_irq);
 }
 
index e8f45c4..3b6a948 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 9cda3fd..6960778 100644 (file)
@@ -129,7 +129,7 @@ static struct spi_board_info neocore926_spi_devices[] = {
                .max_speed_hz   = 125000 * 16,
                .bus_num        = 0,
                .platform_data  = &ads_info,
-               .irq            = AT91SAM9263_ID_IRQ1,
+               .irq            = NR_IRQS_LEGACY + AT91SAM9263_ID_IRQ1,
        },
 #endif
 };
diff --git a/arch/arm/mach-at91/board-rm9200-dt.c b/arch/arm/mach-at91/board-rm9200-dt.c
new file mode 100644 (file)
index 0000000..5f9ce3d
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ *  Setup code for AT91RM9200 Evaluation Kits with Device Tree support
+ *
+ *  Copyright (C) 2011 Atmel,
+ *                2011 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *                2012 Joachim Eastwood <manabian@gmail.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+
+#include <asm/setup.h>
+#include <asm/irq.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include "at91_aic.h"
+#include "generic.h"
+
+
+static const struct of_device_id irq_of_match[] __initconst = {
+       { .compatible = "atmel,at91rm9200-aic", .data = at91_aic_of_init },
+       { /*sentinel*/ }
+};
+
+static void __init at91rm9200_dt_init_irq(void)
+{
+       of_irq_init(irq_of_match);
+}
+
+static void __init at91rm9200_dt_device_init(void)
+{
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char *at91rm9200_dt_board_compat[] __initdata = {
+       "atmel,at91rm9200",
+       NULL
+};
+
+DT_MACHINE_START(at91rm9200_dt, "Atmel AT91RM9200 (Device Tree)")
+       .timer          = &at91rm9200_timer,
+       .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
+       .init_early     = at91rm9200_dt_initialize,
+       .init_irq       = at91rm9200_dt_init_irq,
+       .init_machine   = at91rm9200_dt_device_init,
+       .dt_compat      = at91rm9200_dt_board_compat,
+MACHINE_END
index 27b3af1..a9167dd 100644 (file)
@@ -309,7 +309,7 @@ static struct spi_board_info ek_spi_devices[] = {
                .max_speed_hz   = 125000 * 26,  /* (max sample rate @ 3V) * (cmd + data + overhead) */
                .bus_num        = 0,
                .platform_data  = &ads_info,
-               .irq            = AT91SAM9261_ID_IRQ0,
+               .irq            = NR_IRQS_LEGACY + AT91SAM9261_ID_IRQ0,
                .controller_data = (void *) AT91_PIN_PA28,      /* CS pin */
        },
 #endif
index 073e174..b87dbe2 100644 (file)
@@ -132,7 +132,7 @@ static struct spi_board_info ek_spi_devices[] = {
                .max_speed_hz   = 125000 * 26,  /* (max sample rate @ 3V) * (cmd + data + overhead) */
                .bus_num        = 0,
                .platform_data  = &ads_info,
-               .irq            = AT91SAM9263_ID_IRQ1,
+               .irq            = NR_IRQS_LEGACY + AT91SAM9263_ID_IRQ1,
        },
 #endif
 };
index f496506..fc593d6 100644 (file)
@@ -20,13 +20,15 @@ extern void __init at91_init_sram(int bank, unsigned long base,
 extern void __init at91rm9200_set_type(int type);
 extern void __init at91_initialize(unsigned long main_clock);
 extern void __init at91x40_initialize(unsigned long main_clock);
+extern void __init at91rm9200_dt_initialize(void);
 extern void __init at91_dt_initialize(void);
 
  /* Interrupts */
 extern void __init at91_init_irq_default(void);
 extern void __init at91_init_interrupts(unsigned int priority[]);
 extern void __init at91x40_init_interrupts(unsigned int priority[]);
-extern void __init at91_aic_init(unsigned int priority[]);
+extern void __init at91_aic_init(unsigned int priority[],
+                                unsigned int ext_irq_mask);
 extern int  __init at91_aic_of_init(struct device_node *node,
                                    struct device_node *parent);
 extern int  __init at91_aic5_of_init(struct device_node *node,
index be42cf0..c5d7e1e 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];
index c55a436..a0d92a9 100644 (file)
@@ -70,16 +70,6 @@ struct at91_cf_data {
 extern void __init at91_add_device_cf(struct at91_cf_data *data);
 
  /* MMC / SD */
-  /* at91_mci platform config */
-struct at91_mmc_data {
-       int             det_pin;        /* card detect IRQ */
-       unsigned        slot_b:1;       /* uses Slot B */
-       unsigned        wire4:1;        /* (SD) supports DAT0..DAT3 */
-       int             wp_pin;         /* (SD) writeprotect detect */
-       int             vcc_pin;        /* power switching (high == on) */
-};
-extern void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data);
-
   /* atmel-mci platform config */
 extern void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data);
 
index 1e02c0e..febc2ee 100644 (file)
@@ -502,14 +502,19 @@ int __init at91_aic5_of_init(struct device_node *node,
 /*
  * Initialize the AIC interrupt controller.
  */
-void __init at91_aic_init(unsigned int *priority)
+void __init at91_aic_init(unsigned int *priority, unsigned int ext_irq_mask)
 {
        unsigned int i;
        int irq_base;
 
-       if (at91_aic_pm_init())
+       at91_extern_irq = kzalloc(BITS_TO_LONGS(n_irqs)
+                                 * sizeof(*at91_extern_irq), GFP_KERNEL);
+
+       if (at91_aic_pm_init() || at91_extern_irq == NULL)
                panic("Unable to allocate bit maps\n");
 
+       *at91_extern_irq = ext_irq_mask;
+
        at91_aic_base = ioremap(AT91_AIC, 512);
        if (!at91_aic_base)
                panic("Unable to ioremap AIC registers\n");
index da9881b..19cdd0b 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>
@@ -47,7 +48,7 @@ void __init at91_init_irq_default(void)
 void __init at91_init_interrupts(unsigned int *priority)
 {
        /* Initialize the AIC interrupt controller */
-       at91_aic_init(priority);
+       at91_aic_init(priority, at91_extern_irq);
 
        /* Enable GPIO interrupts */
        at91_gpio_irq_setup();
@@ -151,7 +152,7 @@ static void __init soc_detect(u32 dbgu_base)
        }
 
        /* at91sam9g10 */
-       if ((cidr & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) {
+       if ((socid & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) {
                at91_soc_initdata.type = AT91_SOC_SAM9G10;
                at91_boot_soc = at91sam9261_soc;
        }
@@ -338,6 +339,7 @@ static void at91_dt_rstc(void)
 }
 
 static struct of_device_id ramc_ids[] = {
+       { .compatible = "atmel,at91rm9200-sdramc" },
        { .compatible = "atmel,at91sam9260-sdramc" },
        { .compatible = "atmel,at91sam9g45-ddramc" },
        { /*sentinel*/ }
@@ -436,6 +438,19 @@ end:
        of_node_put(np);
 }
 
+void __init at91rm9200_dt_initialize(void)
+{
+       at91_dt_ramc();
+
+       /* Init clock subsystem */
+       at91_dt_clock_init();
+
+       /* Register the processor-specific clocks */
+       at91_boot_soc.register_clocks();
+
+       at91_boot_soc.init();
+}
+
 void __init at91_dt_initialize(void)
 {
        at91_dt_rstc();
@@ -448,7 +463,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 +479,6 @@ void __init at91_initialize(unsigned long main_clock)
        at91_boot_soc.register_clocks();
 
        at91_boot_soc.init();
+
+       pinctrl_provide_dummies();
 }
index a9cfeb1..9c6d3d4 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 cd0c8b1..14e9947 100644 (file)
@@ -713,8 +713,7 @@ static int dm644x_venc_setup_clock(enum vpbe_enc_timings_type type,
                break;
        case VPBE_ENC_CUSTOM_TIMINGS:
                if (pclock <= 27000000) {
-                       v |= DM644X_VPSS_MUXSEL_PLL2_MODE |
-                            DM644X_VPSS_DACCLKEN;
+                       v |= DM644X_VPSS_DACCLKEN;
                        writel(v, DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL));
                } else {
                        /*
index b37bef1..f723fe1 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 7bcd0df..b47f750 100644 (file)
@@ -63,7 +63,7 @@ static inline int pmu_to_irq(int pin)
 
 static inline int irq_to_pmu(int irq)
 {
-       if (IRQ_DOVE_PMU_START < irq && irq < NR_IRQS)
+       if (IRQ_DOVE_PMU_START <= irq && irq < NR_IRQS)
                return irq - IRQ_DOVE_PMU_START;
 
        return -EINVAL;
index 0877115..bc4344a 100644 (file)
@@ -46,8 +46,20 @@ static void pmu_irq_ack(struct irq_data *d)
        int pin = irq_to_pmu(d->irq);
        u32 u;
 
+       /*
+        * The PMU mask register is not RW0C: it is RW.  This means that
+        * the bits take whatever value is written to them; if you write
+        * a '1', you will set the interrupt.
+        *
+        * Unfortunately this means there is NO race free way to clear
+        * these interrupts.
+        *
+        * So, let's structure the code so that the window is as small as
+        * possible.
+        */
        u = ~(1 << (pin & 31));
-       writel(u, PMU_INTERRUPT_CAUSE);
+       u &= readl_relaxed(PMU_INTERRUPT_CAUSE);
+       writel_relaxed(u, PMU_INTERRUPT_CAUSE);
 }
 
 static struct irq_chip pmu_irq_chip = {
index bb15b26..0ef4435 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 715b690..1947be8 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 21d568b..87e07d6 100644 (file)
@@ -275,6 +275,9 @@ static int __init exynos_dma_init(void)
                exynos_pdma1_pdata.nr_valid_peri =
                        ARRAY_SIZE(exynos4210_pdma1_peri);
                exynos_pdma1_pdata.peri_id = exynos4210_pdma1_peri;
+
+               if (samsung_rev() == EXYNOS4210_REV_0)
+                       exynos_mdma1_device.res.start = EXYNOS4_PA_S_MDMA1;
        } else if (soc_is_exynos4212() || soc_is_exynos4412()) {
                exynos_pdma0_pdata.nr_valid_peri =
                        ARRAY_SIZE(exynos4212_pdma0_peri);
index 8480849..ed4da45 100644 (file)
@@ -90,6 +90,7 @@
 
 #define EXYNOS4_PA_MDMA0               0x10810000
 #define EXYNOS4_PA_MDMA1               0x12850000
+#define EXYNOS4_PA_S_MDMA1             0x12840000
 #define EXYNOS4_PA_PDMA0               0x12680000
 #define EXYNOS4_PA_PDMA1               0x12690000
 #define EXYNOS5_PA_MDMA0               0x10800000
index e58d786..eadf4b5 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 82c2723..86e37cd 100644 (file)
@@ -28,6 +28,7 @@ void highbank_restart(char mode, const char *cmd)
                hignbank_set_pwr_soft_reset();
 
        scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
-       cpu_do_idle();
+       while (1)
+               cpu_do_idle();
 }
 
index 1a7a8dd..1ab91b5 100644 (file)
@@ -108,7 +108,7 @@ struct clk *imx_clk_busy_divider(const char *name, const char *parent_name,
        busy->div.hw.init = &init;
 
        clk = clk_register(NULL, &busy->div.hw);
-       if (!clk)
+       if (IS_ERR(clk))
                kfree(busy);
 
        return clk;
index 3c1b8ff..cc49c7a 100644 (file)
@@ -112,7 +112,7 @@ struct clk *clk_register_gate2(struct device *dev, const char *name,
 
        clk = clk_register(dev, &gate->hw);
        if (IS_ERR(clk))
-               kfree(clk);
+               kfree(gate);
 
        return clk;
 }
index d20d479..01e2f84 100644 (file)
@@ -127,8 +127,8 @@ int __init mx25_clocks_init(void)
        clk[esdhc2_ipg_per] = imx_clk_gate("esdhc2_ipg_per", "per4", ccm(CCM_CGCR0),  4);
        clk[gpt_ipg_per] = imx_clk_gate("gpt_ipg_per", "per5", ccm(CCM_CGCR0),  5);
        clk[i2c_ipg_per] = imx_clk_gate("i2c_ipg_per", "per6", ccm(CCM_CGCR0),  6);
-       clk[lcdc_ipg_per] = imx_clk_gate("lcdc_ipg_per", "per8", ccm(CCM_CGCR0),  7);
-       clk[nfc_ipg_per] = imx_clk_gate("nfc_ipg_per", "ipg_per", ccm(CCM_CGCR0),  8);
+       clk[lcdc_ipg_per] = imx_clk_gate("lcdc_ipg_per", "per7", ccm(CCM_CGCR0),  7);
+       clk[nfc_ipg_per] = imx_clk_gate("nfc_ipg_per", "per8", ccm(CCM_CGCR0),  8);
        clk[ssi1_ipg_per] = imx_clk_gate("ssi1_ipg_per", "per13", ccm(CCM_CGCR0), 13);
        clk[ssi2_ipg_per] = imx_clk_gate("ssi2_ipg_per", "per14", ccm(CCM_CGCR0), 14);
        clk[uart_ipg_per] = imx_clk_gate("uart_ipg_per", "per15", ccm(CCM_CGCR0), 15);
index 3b6b640..366e5d5 100644 (file)
@@ -109,7 +109,7 @@ int __init mx27_clocks_init(unsigned long fref)
        clk[per3_div] = imx_clk_divider("per3_div", "mpll_main2", CCM_PCDR1, 16, 6);
        clk[per4_div] = imx_clk_divider("per4_div", "mpll_main2", CCM_PCDR1, 24, 6);
        clk[vpu_sel] = imx_clk_mux("vpu_sel", CCM_CSCR, 21, 1, vpu_sel_clks, ARRAY_SIZE(vpu_sel_clks));
-       clk[vpu_div] = imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 3);
+       clk[vpu_div] = imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 6);
        clk[usb_div] = imx_clk_divider("usb_div", "spll", CCM_CSCR, 28, 3);
        clk[cpu_sel] = imx_clk_mux("cpu_sel", CCM_CSCR, 15, 1, cpu_sel_clks, ARRAY_SIZE(cpu_sel_clks));
        clk[clko_sel] = imx_clk_mux("clko_sel", CCM_CCSR, 0, 5, clko_sel_clks, ARRAY_SIZE(clko_sel_clks));
@@ -121,7 +121,7 @@ int __init mx27_clocks_init(unsigned long fref)
        clk[ssi1_sel] = imx_clk_mux("ssi1_sel", CCM_CSCR, 22, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
        clk[ssi2_sel] = imx_clk_mux("ssi2_sel", CCM_CSCR, 23, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
        clk[ssi1_div] = imx_clk_divider("ssi1_div", "ssi1_sel", CCM_PCDR0, 16, 6);
-       clk[ssi2_div] = imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 3);
+       clk[ssi2_div] = imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 6);
        clk[clko_en] = imx_clk_gate("clko_en", "clko_div", CCM_PCCR0, 0);
        clk[ssi2_ipg_gate] = imx_clk_gate("ssi2_ipg_gate", "ipg", CCM_PCCR0, 0);
        clk[ssi1_ipg_gate] = imx_clk_gate("ssi1_ipg_gate", "ipg", CCM_PCCR0, 1);
index 412c583..576af74 100644 (file)
@@ -30,7 +30,7 @@
 #define MX25_H1_SIC_SHIFT      21
 #define MX25_H1_SIC_MASK       (0x3 << MX25_H1_SIC_SHIFT)
 #define MX25_H1_PP_BIT         (1 << 18)
-#define MX25_H1_PM_BIT         (1 << 8)
+#define MX25_H1_PM_BIT         (1 << 16)
 #define MX25_H1_IPPUE_UP_BIT   (1 << 7)
 #define MX25_H1_IPPUE_DOWN_BIT (1 << 6)
 #define MX25_H1_TLL_BIT                (1 << 5)
index 779e16e..2933978 100644 (file)
@@ -30,7 +30,7 @@
 #define MX35_H1_SIC_SHIFT      21
 #define MX35_H1_SIC_MASK       (0x3 << MX35_H1_SIC_SHIFT)
 #define MX35_H1_PP_BIT         (1 << 18)
-#define MX35_H1_PM_BIT         (1 << 8)
+#define MX35_H1_PM_BIT         (1 << 16)
 #define MX35_H1_IPPUE_UP_BIT   (1 << 7)
 #define MX35_H1_IPPUE_DOWN_BIT (1 << 6)
 #define MX35_H1_TLL_BIT                (1 << 5)
index 9d2c843..b5deb05 100644 (file)
@@ -108,9 +108,8 @@ void __init imx3_init_l2x0(void)
        }
 
        l2x0_base = ioremap(MX3x_L2CC_BASE_ADDR, 4096);
-       if (IS_ERR(l2x0_base)) {
-               printk(KERN_ERR "remapping L2 cache area failed with %ld\n",
-                               PTR_ERR(l2x0_base));
+       if (!l2x0_base) {
+               printk(KERN_ERR "remapping L2 cache area failed\n");
                return;
        }
 
index e428f3a..b3d86d7 100644 (file)
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
 #include <linux/io.h>
+#include <linux/platform_data/clk-integrator.h>
 #include <linux/slab.h>
-#include <linux/clkdev.h>
 
-#include <asm/hardware/icst.h>
 #include <mach/lm.h>
 #include <mach/impd1.h>
 #include <asm/sizes.h>
@@ -36,45 +35,6 @@ MODULE_PARM_DESC(lmid, "logic module stack position");
 
 struct impd1_module {
        void __iomem    *base;
-       struct clk      vcos[2];
-       struct clk_lookup *clks[3];
-};
-
-static const struct icst_params impd1_vco_params = {
-       .ref            = 24000000,     /* 24 MHz */
-       .vco_max        = ICST525_VCO_MAX_3V,
-       .vco_min        = ICST525_VCO_MIN,
-       .vd_min         = 12,
-       .vd_max         = 519,
-       .rd_min         = 3,
-       .rd_max         = 120,
-       .s2div          = icst525_s2div,
-       .idx2s          = icst525_idx2s,
-};
-
-static void impd1_setvco(struct clk *clk, struct icst_vco vco)
-{
-       struct impd1_module *impd1 = clk->data;
-       u32 val = vco.v | (vco.r << 9) | (vco.s << 16);
-
-       writel(0xa05f, impd1->base + IMPD1_LOCK);
-       writel(val, clk->vcoreg);
-       writel(0, impd1->base + IMPD1_LOCK);
-
-#ifdef DEBUG
-       vco.v = val & 0x1ff;
-       vco.r = (val >> 9) & 0x7f;
-       vco.s = (val >> 16) & 7;
-
-       pr_debug("IM-PD1: VCO%d clock is %ld Hz\n",
-                vconr, icst525_hz(&impd1_vco_params, vco));
-#endif
-}
-
-static const struct clk_ops impd1_clk_ops = {
-       .round  = icst_clk_round,
-       .set    = icst_clk_set,
-       .setvco = impd1_setvco,
 };
 
 void impd1_tweak_control(struct device *dev, u32 mask, u32 val)
@@ -344,10 +304,6 @@ static struct impd1_device impd1_devs[] = {
        }
 };
 
-static struct clk fixed_14745600 = {
-       .rate = 14745600,
-};
-
 static int impd1_probe(struct lm_device *dev)
 {
        struct impd1_module *impd1;
@@ -376,23 +332,7 @@ static int impd1_probe(struct lm_device *dev)
        printk("IM-PD1 found at 0x%08lx\n",
                (unsigned long)dev->resource.start);
 
-       for (i = 0; i < ARRAY_SIZE(impd1->vcos); i++) {
-               impd1->vcos[i].ops = &impd1_clk_ops,
-               impd1->vcos[i].owner = THIS_MODULE,
-               impd1->vcos[i].params = &impd1_vco_params,
-               impd1->vcos[i].data = impd1;
-       }
-       impd1->vcos[0].vcoreg = impd1->base + IMPD1_OSC1;
-       impd1->vcos[1].vcoreg = impd1->base + IMPD1_OSC2;
-
-       impd1->clks[0] = clkdev_alloc(&impd1->vcos[0], NULL, "lm%x:01000",
-                                       dev->id);
-       impd1->clks[1] = clkdev_alloc(&fixed_14745600, NULL, "lm%x:00100",
-                                       dev->id);
-       impd1->clks[2] = clkdev_alloc(&fixed_14745600, NULL, "lm%x:00200",
-                                       dev->id);
-       for (i = 0; i < ARRAY_SIZE(impd1->clks); i++)
-               clkdev_add(impd1->clks[i]);
+       integrator_impd1_clk_init(impd1->base, dev->id);
 
        for (i = 0; i < ARRAY_SIZE(impd1_devs); i++) {
                struct impd1_device *idev = impd1_devs + i;
@@ -431,12 +371,9 @@ static int impd1_remove_one(struct device *dev, void *data)
 static void impd1_remove(struct lm_device *dev)
 {
        struct impd1_module *impd1 = lm_get_drvdata(dev);
-       int i;
 
        device_for_each_child(&dev->dev, NULL, impd1_remove_one);
-
-       for (i = 0; i < ARRAY_SIZE(impd1->clks); i++)
-               clkdev_drop(impd1->clks[i]);
+       integrator_impd1_clk_exit(dev->id);
 
        lm_set_drvdata(dev, NULL);
 
index 1694f01..6d6bde3 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 fdf91a1..8c0c0e2 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 b800a03..53b8348 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 8c9f8d5..ff686cb 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 eb68b61..c5bae9c 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 9e7cad2..4de8da5 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 a17ed79..d4eb09a 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 852f7c9..9d1b6b7 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 70c5a28..d94872f 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 3991077..2c6c218 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 ec54491..74fc5a0 100644 (file)
@@ -207,14 +207,19 @@ static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
        return 1;
 }
 
+/*
+ * The root complex has a hardwired class of PCI_CLASS_MEMORY_OTHER, when it
+ * is operating as a root complex this needs to be switched to
+ * PCI_CLASS_BRIDGE_HOST or Linux will errantly try to process the BAR's on
+ * the device. Decoding setup is handled by the orion code.
+ */
 static void __devinit rc_pci_fixup(struct pci_dev *dev)
 {
-       /*
-        * Prevent enumeration of root complex.
-        */
        if (dev->bus->parent == NULL && dev->devfn == 0) {
                int i;
 
+               dev->class &= 0xff;
+               dev->class |= PCI_CLASS_BRIDGE_HOST << 8;
                for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
                        dev->resource[i].start = 0;
                        dev->resource[i].end   = 0;
index bfa1eab..22ef8a1 100644 (file)
@@ -24,6 +24,7 @@
 #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>
@@ -32,9 +33,7 @@
 #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>
index b617eae..1273931 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 6d14454..0c2f662 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.
index 9518bf5..e255164 100644 (file)
@@ -444,16 +444,28 @@ static struct omap1_cam_platform_data ams_delta_camera_platform_data = {
        .lclk_khz_max   = 1334,         /* results in 5fps CIF, 10fps QCIF */
 };
 
+static struct platform_device ams_delta_audio_device = {
+       .name   = "ams-delta-audio",
+       .id     = -1,
+};
+
+static struct platform_device cx20442_codec_device = {
+       .name   = "cx20442-codec",
+       .id     = -1,
+};
+
 static struct platform_device *ams_delta_devices[] __initdata = {
        &latch1_gpio_device,
        &latch2_gpio_device,
        &ams_delta_kp_device,
        &ams_delta_camera_device,
+       &ams_delta_audio_device,
 };
 
 static struct platform_device *late_devices[] __initdata = {
        &ams_delta_nand_device,
        &ams_delta_lcd_device,
+       &cx20442_codec_device,
 };
 
 static void __init ams_delta_init(void)
index 2a1a898..d669e22 100644 (file)
@@ -11,7 +11,6 @@ config ARCH_OMAP2PLUS_TYPICAL
        select I2C_OMAP
        select MENELAUS if ARCH_OMAP2
        select NEON if ARCH_OMAP3 || ARCH_OMAP4 || SOC_OMAP5
-       select PINCTRL
        select PM_RUNTIME
        select REGULATOR
        select SERIAL_OMAP
index 48d5e41..3785906 100644 (file)
@@ -580,6 +580,11 @@ static void __init igep_wlan_bt_init(void)
        } else
                return;
 
+       /* Make sure that the GPIO pins are muxed correctly */
+       omap_mux_init_gpio(igep_wlan_bt_gpios[0].gpio, OMAP_PIN_OUTPUT);
+       omap_mux_init_gpio(igep_wlan_bt_gpios[1].gpio, OMAP_PIN_OUTPUT);
+       omap_mux_init_gpio(igep_wlan_bt_gpios[2].gpio, OMAP_PIN_OUTPUT);
+
        err = gpio_request_array(igep_wlan_bt_gpios,
                                 ARRAY_SIZE(igep_wlan_bt_gpios));
        if (err) {
index 388c431..d41ab98 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
 #include <linux/opp.h>
+#include <linux/cpu.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -444,27 +445,31 @@ static struct omap_board_mux board_mux[] __initdata = {
 };
 #endif
 
-static void __init beagle_opp_init(void)
+static int __init beagle_opp_init(void)
 {
        int r = 0;
 
-       /* Initialize the omap3 opp table */
-       if (omap3_opp_init()) {
+       if (!machine_is_omap3_beagle())
+               return 0;
+
+       /* Initialize the omap3 opp table if not already created. */
+       r = omap3_opp_init();
+       if (IS_ERR_VALUE(r) && (r != -EEXIST)) {
                pr_err("%s: opp default init failed\n", __func__);
-               return;
+               return r;
        }
 
        /* Custom OPP enabled for all xM versions */
        if (cpu_is_omap3630()) {
                struct device *mpu_dev, *iva_dev;
 
-               mpu_dev = omap_device_get_by_hwmod_name("mpu");
+               mpu_dev = get_cpu_device(0);
                iva_dev = omap_device_get_by_hwmod_name("iva");
 
                if (IS_ERR(mpu_dev) || IS_ERR(iva_dev)) {
                        pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n",
                                __func__, mpu_dev, iva_dev);
-                       return;
+                       return -ENODEV;
                }
                /* Enable MPU 1GHz and lower opps */
                r = opp_enable(mpu_dev, 800000000);
@@ -484,8 +489,9 @@ static void __init beagle_opp_init(void)
                        opp_disable(iva_dev, 660000000);
                }
        }
-       return;
+       return 0;
 }
+device_initcall(beagle_opp_init);
 
 static void __init omap3_beagle_init(void)
 {
@@ -522,8 +528,6 @@ static void __init omap3_beagle_init(void)
        /* Ensure SDRC pins are mux'd for self-refresh */
        omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
        omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
-
-       beagle_opp_init();
 }
 
 MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
index 114ab4b..1a45d6b 100644 (file)
@@ -1073,6 +1073,8 @@ static struct omap_clk am33xx_clks[] = {
        CLK(NULL,       "gfx_fck_div_ck",       &gfx_fck_div_ck,        CK_AM33XX),
        CLK(NULL,       "sysclkout_pre_ck",     &sysclkout_pre_ck,      CK_AM33XX),
        CLK(NULL,       "clkout2_ck",           &clkout2_ck,    CK_AM33XX),
+       CLK(NULL,       "timer_32k_ck",         &clkdiv32k_ick, CK_AM33XX),
+       CLK(NULL,       "timer_sys_ck",         &sys_clkin_ck,  CK_AM33XX),
 };
 
 int __init am33xx_clk_init(void)
index d661d13..6efc30c 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 cbb8791..512e79a 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 b56d06b..95192a0 100644 (file)
@@ -359,7 +359,7 @@ static struct clockdomain iss_44xx_clkdm = {
        .clkdm_offs       = OMAP4430_CM2_CAM_CAM_CDOFFS,
        .wkdep_srcs       = iss_wkup_sleep_deps,
        .sleepdep_srcs    = iss_wkup_sleep_deps,
-       .flags            = CLKDM_CAN_HWSUP_SWSUP,
+       .flags            = CLKDM_CAN_SWSUP,
 };
 
 static struct clockdomain l3_dss_44xx_clkdm = {
index 48daac2..84551f2 100644 (file)
@@ -64,30 +64,36 @@ void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
        struct spi_board_info *spi_bi = &ads7846_spi_board_info;
        int err;
 
-       err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown");
-       if (err) {
-               pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err);
-               return;
-       }
+       /*
+        * If a board defines get_pendown_state() function, request the pendown
+        * GPIO and set the GPIO debounce time.
+        * If a board does not define the get_pendown_state() function, then
+        * the ads7846 driver will setup the pendown GPIO itself.
+        */
+       if (board_pdata && board_pdata->get_pendown_state) {
+               err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown");
+               if (err) {
+                       pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err);
+                       return;
+               }
 
-       if (gpio_debounce)
-               gpio_set_debounce(gpio_pendown, gpio_debounce);
+               if (gpio_debounce)
+                       gpio_set_debounce(gpio_pendown, gpio_debounce);
+
+               gpio_export(gpio_pendown, 0);
+       }
 
        spi_bi->bus_num = bus_num;
        spi_bi->irq     = gpio_to_irq(gpio_pendown);
 
+       ads7846_config.gpio_pendown = gpio_pendown;
+
        if (board_pdata) {
                board_pdata->gpio_pendown = gpio_pendown;
+               board_pdata->gpio_pendown_debounce = gpio_debounce;
                spi_bi->platform_data = board_pdata;
-               if (board_pdata->get_pendown_state)
-                       gpio_export(gpio_pendown, 0);
-       } else {
-               ads7846_config.gpio_pendown = gpio_pendown;
        }
 
-       if (!board_pdata || (board_pdata && !board_pdata->get_pendown_state))
-               gpio_free(gpio_pendown);
-
        spi_register_board_info(&ads7846_spi_board_info, 1);
 }
 #else
index c8c2117..c72b5a7 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/of.h>
 #include <linux/pinctrl/machine.h>
 #include <linux/platform_data/omap4-keypad.h>
+#include <linux/platform_data/omap_ocp2scp.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
@@ -341,7 +342,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;
        }
 
@@ -613,6 +614,83 @@ static void omap_init_vout(void)
 static inline void omap_init_vout(void) {}
 #endif
 
+#if defined(CONFIG_OMAP_OCP2SCP) || defined(CONFIG_OMAP_OCP2SCP_MODULE)
+static int count_ocp2scp_devices(struct omap_ocp2scp_dev *ocp2scp_dev)
+{
+       int cnt = 0;
+
+       while (ocp2scp_dev->drv_name != NULL) {
+               cnt++;
+               ocp2scp_dev++;
+       }
+
+       return cnt;
+}
+
+static void omap_init_ocp2scp(void)
+{
+       struct omap_hwmod       *oh;
+       struct platform_device  *pdev;
+       int                     bus_id = -1, dev_cnt = 0, i;
+       struct omap_ocp2scp_dev *ocp2scp_dev;
+       const char              *oh_name, *name;
+       struct omap_ocp2scp_platform_data *pdata;
+
+       if (!cpu_is_omap44xx())
+               return;
+
+       oh_name = "ocp2scp_usb_phy";
+       name    = "omap-ocp2scp";
+
+       oh = omap_hwmod_lookup(oh_name);
+       if (!oh) {
+               pr_err("%s: could not find omap_hwmod for %s\n", __func__,
+                                                               oh_name);
+               return;
+       }
+
+       pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+       if (!pdata) {
+               pr_err("%s: No memory for ocp2scp pdata\n", __func__);
+               return;
+       }
+
+       ocp2scp_dev = oh->dev_attr;
+       dev_cnt = count_ocp2scp_devices(ocp2scp_dev);
+
+       if (!dev_cnt) {
+               pr_err("%s: No devices connected to ocp2scp\n", __func__);
+               kfree(pdata);
+               return;
+       }
+
+       pdata->devices = kzalloc(sizeof(struct omap_ocp2scp_dev *)
+                                       * dev_cnt, GFP_KERNEL);
+       if (!pdata->devices) {
+               pr_err("%s: No memory for ocp2scp pdata devices\n", __func__);
+               kfree(pdata);
+               return;
+       }
+
+       for (i = 0; i < dev_cnt; i++, ocp2scp_dev++)
+               pdata->devices[i] = ocp2scp_dev;
+
+       pdata->dev_cnt  = dev_cnt;
+
+       pdev = omap_device_build(name, bus_id, oh, pdata, sizeof(*pdata), NULL,
+                                                               0, false);
+       if (IS_ERR(pdev)) {
+               pr_err("Could not build omap_device for %s %s\n",
+                                               name, oh_name);
+               kfree(pdata->devices);
+               kfree(pdata);
+               return;
+       }
+}
+#else
+static inline void omap_init_ocp2scp(void) { }
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 static int __init omap2_init_devices(void)
@@ -640,6 +718,7 @@ static int __init omap2_init_devices(void)
        omap_init_sham();
        omap_init_aes();
        omap_init_vout();
+       omap_init_ocp2scp();
 
        return 0;
 }
index 5ac5cf3..92b5718 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 17f80e4..c47140b 100644 (file)
@@ -614,16 +614,16 @@ static struct omap_mux __initdata omap3_muxmodes[] = {
                "sys_off_mode", NULL, NULL, NULL,
                "gpio_9", NULL, NULL, "safe_mode"),
        _OMAP3_MUXENTRY(UART1_CTS, 150,
-               "uart1_cts", NULL, NULL, NULL,
+               "uart1_cts", "ssi1_rdy_tx", NULL, NULL,
                "gpio_150", "hsusb3_tll_clk", NULL, "safe_mode"),
        _OMAP3_MUXENTRY(UART1_RTS, 149,
-               "uart1_rts", NULL, NULL, NULL,
+               "uart1_rts", "ssi1_flag_tx", NULL, NULL,
                "gpio_149", NULL, NULL, "safe_mode"),
        _OMAP3_MUXENTRY(UART1_RX, 151,
-               "uart1_rx", NULL, "mcbsp1_clkr", "mcspi4_clk",
+               "uart1_rx", "ss1_wake_tx", "mcbsp1_clkr", "mcspi4_clk",
                "gpio_151", NULL, NULL, "safe_mode"),
        _OMAP3_MUXENTRY(UART1_TX, 148,
-               "uart1_tx", NULL, NULL, NULL,
+               "uart1_tx", "ssi1_dat_tx", NULL, NULL,
                "gpio_148", NULL, NULL, "safe_mode"),
        _OMAP3_MUXENTRY(UART2_CTS, 144,
                "uart2_cts", "mcbsp3_dx", "gpt9_pwm_evt", NULL,
index b969ab1..87cc6d0 100644 (file)
@@ -422,6 +422,38 @@ static int _set_softreset(struct omap_hwmod *oh, u32 *v)
 }
 
 /**
+ * _wait_softreset_complete - wait for an OCP softreset to complete
+ * @oh: struct omap_hwmod * to wait on
+ *
+ * Wait until the IP block represented by @oh reports that its OCP
+ * softreset is complete.  This can be triggered by software (see
+ * _ocp_softreset()) or by hardware upon returning from off-mode (one
+ * example is HSMMC).  Waits for up to MAX_MODULE_SOFTRESET_WAIT
+ * microseconds.  Returns the number of microseconds waited.
+ */
+static int _wait_softreset_complete(struct omap_hwmod *oh)
+{
+       struct omap_hwmod_class_sysconfig *sysc;
+       u32 softrst_mask;
+       int c = 0;
+
+       sysc = oh->class->sysc;
+
+       if (sysc->sysc_flags & SYSS_HAS_RESET_STATUS)
+               omap_test_timeout((omap_hwmod_read(oh, sysc->syss_offs)
+                                  & SYSS_RESETDONE_MASK),
+                                 MAX_MODULE_SOFTRESET_WAIT, c);
+       else if (sysc->sysc_flags & SYSC_HAS_RESET_STATUS) {
+               softrst_mask = (0x1 << sysc->sysc_fields->srst_shift);
+               omap_test_timeout(!(omap_hwmod_read(oh, sysc->sysc_offs)
+                                   & softrst_mask),
+                                 MAX_MODULE_SOFTRESET_WAIT, c);
+       }
+
+       return c;
+}
+
+/**
  * _set_dmadisable: set OCP_SYSCONFIG.DMADISABLE bit in @v
  * @oh: struct omap_hwmod *
  *
@@ -1282,6 +1314,18 @@ static void _enable_sysc(struct omap_hwmod *oh)
        if (!oh->class->sysc)
                return;
 
+       /*
+        * Wait until reset has completed, this is needed as the IP
+        * block is reset automatically by hardware in some cases
+        * (off-mode for example), and the drivers require the
+        * IP to be ready when they access it
+        */
+       if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
+               _enable_optional_clocks(oh);
+       _wait_softreset_complete(oh);
+       if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
+               _disable_optional_clocks(oh);
+
        v = oh->_sysc_cache;
        sf = oh->class->sysc->sysc_flags;
 
@@ -1804,7 +1848,7 @@ static int _am33xx_disable_module(struct omap_hwmod *oh)
  */
 static int _ocp_softreset(struct omap_hwmod *oh)
 {
-       u32 v, softrst_mask;
+       u32 v;
        int c = 0;
        int ret = 0;
 
@@ -1834,19 +1878,7 @@ static int _ocp_softreset(struct omap_hwmod *oh)
        if (oh->class->sysc->srst_udelay)
                udelay(oh->class->sysc->srst_udelay);
 
-       if (oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS)
-               omap_test_timeout((omap_hwmod_read(oh,
-                                                   oh->class->sysc->syss_offs)
-                                  & SYSS_RESETDONE_MASK),
-                                 MAX_MODULE_SOFTRESET_WAIT, c);
-       else if (oh->class->sysc->sysc_flags & SYSC_HAS_RESET_STATUS) {
-               softrst_mask = (0x1 << oh->class->sysc->sysc_fields->srst_shift);
-               omap_test_timeout(!(omap_hwmod_read(oh,
-                                                    oh->class->sysc->sysc_offs)
-                                  & softrst_mask),
-                                 MAX_MODULE_SOFTRESET_WAIT, c);
-       }
-
+       c = _wait_softreset_complete(oh);
        if (c == MAX_MODULE_SOFTRESET_WAIT)
                pr_warning("omap_hwmod: %s: softreset failed (waited %d usec)\n",
                           oh->name, MAX_MODULE_SOFTRESET_WAIT);
@@ -2352,6 +2384,9 @@ static int __init _setup_reset(struct omap_hwmod *oh)
        if (oh->_state != _HWMOD_STATE_INITIALIZED)
                return -EINVAL;
 
+       if (oh->flags & HWMOD_EXT_OPT_MAIN_CLK)
+               return -EPERM;
+
        if (oh->rst_lines_cnt == 0) {
                r = _enable(oh);
                if (r) {
index 652d028..0b1249e 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/io.h>
 #include <linux/platform_data/gpio-omap.h>
 #include <linux/power/smartreflex.h>
+#include <linux/platform_data/omap_ocp2scp.h>
 
 #include <plat/omap_hwmod.h>
 #include <plat/i2c.h>
@@ -2125,6 +2126,14 @@ static struct omap_hwmod omap44xx_mcpdm_hwmod = {
        .name           = "mcpdm",
        .class          = &omap44xx_mcpdm_hwmod_class,
        .clkdm_name     = "abe_clkdm",
+       /*
+        * It's suspected that the McPDM requires an off-chip main
+        * functional clock, controlled via I2C.  This IP block is
+        * currently reset very early during boot, before I2C is
+        * available, so it doesn't seem that we have any choice in
+        * the kernel other than to avoid resetting it.
+        */
+       .flags          = HWMOD_EXT_OPT_MAIN_CLK,
        .mpu_irqs       = omap44xx_mcpdm_irqs,
        .sdma_reqs      = omap44xx_mcpdm_sdma_reqs,
        .main_clk       = "mcpdm_fck",
@@ -2681,6 +2690,32 @@ static struct omap_hwmod_class omap44xx_ocp2scp_hwmod_class = {
        .sysc   = &omap44xx_ocp2scp_sysc,
 };
 
+/* ocp2scp dev_attr */
+static struct resource omap44xx_usb_phy_and_pll_addrs[] = {
+       {
+               .name           = "usb_phy",
+               .start          = 0x4a0ad080,
+               .end            = 0x4a0ae000,
+               .flags          = IORESOURCE_MEM,
+       },
+       {
+               /* XXX: Remove this once control module driver is in place */
+               .name           = "ctrl_dev",
+               .start          = 0x4a002300,
+               .end            = 0x4a002303,
+               .flags          = IORESOURCE_MEM,
+       },
+       { }
+};
+
+static struct omap_ocp2scp_dev ocp2scp_dev_attr[] = {
+       {
+               .drv_name       = "omap-usb2",
+               .res            = omap44xx_usb_phy_and_pll_addrs,
+       },
+       { }
+};
+
 /* ocp2scp_usb_phy */
 static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = {
        .name           = "ocp2scp_usb_phy",
@@ -2694,6 +2729,7 @@ static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = {
                        .modulemode   = MODULEMODE_HWCTRL,
                },
        },
+       .dev_attr       = ocp2scp_dev_attr,
 };
 
 /*
index 686137d..67d6613 100644 (file)
@@ -91,6 +91,7 @@ extern void omap3_save_scratchpad_contents(void);
 
 #define PM_RTA_ERRATUM_i608            (1 << 0)
 #define PM_SDRC_WAKEUP_ERRATUM_i583    (1 << 1)
+#define PM_PER_MEMORIES_ERRATUM_i582   (1 << 2)
 
 #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
 extern u16 pm34xx_errata;
index ba670db..3a904de 100644 (file)
@@ -652,14 +652,17 @@ static void __init pm_errata_configure(void)
                /* Enable the l2 cache toggling in sleep logic */
                enable_omap3630_toggle_l2_on_restore();
                if (omap_rev() < OMAP3630_REV_ES1_2)
-                       pm34xx_errata |= PM_SDRC_WAKEUP_ERRATUM_i583;
+                       pm34xx_errata |= (PM_SDRC_WAKEUP_ERRATUM_i583 |
+                                         PM_PER_MEMORIES_ERRATUM_i582);
+       } else if (cpu_is_omap34xx()) {
+               pm34xx_errata |= PM_PER_MEMORIES_ERRATUM_i582;
        }
 }
 
 int __init omap3_pm_init(void)
 {
        struct power_state *pwrst, *tmp;
-       struct clockdomain *neon_clkdm, *mpu_clkdm;
+       struct clockdomain *neon_clkdm, *mpu_clkdm, *per_clkdm, *wkup_clkdm;
        int ret;
 
        if (!omap3_has_io_chain_ctrl())
@@ -711,6 +714,8 @@ int __init omap3_pm_init(void)
 
        neon_clkdm = clkdm_lookup("neon_clkdm");
        mpu_clkdm = clkdm_lookup("mpu_clkdm");
+       per_clkdm = clkdm_lookup("per_clkdm");
+       wkup_clkdm = clkdm_lookup("wkup_clkdm");
 
 #ifdef CONFIG_SUSPEND
        omap_pm_suspend = omap3_pm_suspend;
@@ -727,6 +732,27 @@ int __init omap3_pm_init(void)
        if (IS_PM34XX_ERRATUM(PM_RTA_ERRATUM_i608))
                omap3630_ctrl_disable_rta();
 
+       /*
+        * The UART3/4 FIFO and the sidetone memory in McBSP2/3 are
+        * not correctly reset when the PER powerdomain comes back
+        * from OFF or OSWR when the CORE powerdomain is kept active.
+        * See OMAP36xx Erratum i582 "PER Domain reset issue after
+        * Domain-OFF/OSWR Wakeup".  This wakeup dependency is not a
+        * complete workaround.  The kernel must also prevent the PER
+        * powerdomain from going to OSWR/OFF while the CORE
+        * powerdomain is not going to OSWR/OFF.  And if PER last
+        * power state was off while CORE last power state was ON, the
+        * UART3/4 and McBSP2/3 SIDETONE devices need to run a
+        * self-test using their loopback tests; if that fails, those
+        * devices are unusable until the PER/CORE can complete a transition
+        * from ON to OSWR/OFF and then back to ON.
+        *
+        * XXX Technically this workaround is only needed if off-mode
+        * or OSWR is enabled.
+        */
+       if (IS_PM34XX_ERRATUM(PM_PER_MEMORIES_ERRATUM_i582))
+               clkdm_add_wkdep(per_clkdm, wkup_clkdm);
+
        clkdm_add_wkdep(neon_clkdm, mpu_clkdm);
        if (omap_type() != OMAP2_DEVICE_TYPE_GP) {
                omap3_secure_ram_storage =
index 0405c81..a507cd6 100644 (file)
@@ -329,6 +329,11 @@ void __init omap_serial_init_port(struct omap_board_data *bdata,
 
        oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
 
+       if (console_uart_id == bdata->id) {
+               omap_device_enable(pdev);
+               pm_runtime_set_active(&pdev->dev);
+       }
+
        oh->dev_attr = uart;
 
        if (((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads)
index 44f9aa7..69e4663 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 635e109..a256135 100644 (file)
@@ -73,6 +73,7 @@ void __init omap4_pmic_init(const char *pmic_type,
 {
        /* PMIC part*/
        omap_mux_init_signal("sys_nirq1", OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE);
+       omap_mux_init_signal("fref_clk0_out.sys_drm_msecure", OMAP_PIN_OUTPUT);
        omap_pmic_init(1, 400, pmic_type, 7 + OMAP44XX_IRQ_GIC_START, pmic_data);
 
        /* Register additional devices on i2c1 bus if needed */
@@ -366,7 +367,7 @@ static struct regulator_init_data omap4_clk32kg_idata = {
 };
 
 static struct regulator_consumer_supply omap4_vdd1_supply[] = {
-       REGULATOR_SUPPLY("vcc", "mpu.0"),
+       REGULATOR_SUPPLY("vcc", "cpu0"),
 };
 
 static struct regulator_consumer_supply omap4_vdd2_supply[] = {
index 880249b..75878c3 100644 (file)
@@ -264,7 +264,7 @@ static void __init omap_vc_i2c_init(struct voltagedomain *voltdm)
 
        if (initialized) {
                if (voltdm->pmic->i2c_high_speed != i2c_high_speed)
-                       pr_warn("%s: I2C config for vdd_%s does not match other channels (%u).",
+                       pr_warn("%s: I2C config for vdd_%s does not match other channels (%u).\n",
                                __func__, voltdm->name, i2c_high_speed);
                return;
        }
diff --git a/arch/arm/mach-prima2/include/mach/gpio.h b/arch/arm/mach-prima2/include/mach/gpio.h
deleted file mode 100644 (file)
index 1904bb0..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __MACH_GPIO_H
-#define __MACH_GPIO_H
-
-/* Pull up/down values */
-enum sirfsoc_gpio_pull {
-       SIRFSOC_GPIO_PULL_NONE,
-       SIRFSOC_GPIO_PULL_UP,
-       SIRFSOC_GPIO_PULL_DOWN,
-};
-
-void sirfsoc_gpio_set_pull(unsigned gpio, unsigned mode);
-
-#endif
index 5ecbd17..e2c6391 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/mfd/asic3.h>
 #include <linux/mtd/physmap.h>
 #include <linux/pda_power.h>
+#include <linux/pwm.h>
 #include <linux/pwm_backlight.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/gpio-regulator.h>
@@ -556,7 +557,7 @@ static struct platform_device hx4700_lcd = {
  */
 
 static struct platform_pwm_backlight_data backlight_data = {
-       .pwm_id         = 1,
+       .pwm_id         = -1,   /* Superseded by pwm_lookup */
        .max_brightness = 200,
        .dft_brightness = 100,
        .pwm_period_ns  = 30923,
@@ -571,6 +572,10 @@ static struct platform_device backlight = {
        },
 };
 
+static struct pwm_lookup hx4700_pwm_lookup[] = {
+       PWM_LOOKUP("pxa27x-pwm.1", 0, "pwm-backlight", NULL),
+};
+
 /*
  * USB "Transceiver"
  */
@@ -872,6 +877,7 @@ static void __init hx4700_init(void)
        pxa_set_stuart_info(NULL);
 
        platform_add_devices(devices, ARRAY_SIZE(devices));
+       pwm_add_table(hx4700_pwm_lookup, ARRAY_SIZE(hx4700_pwm_lookup));
 
        pxa_set_ficp_info(&ficp_info);
        pxa27x_set_i2c_power_info(NULL);
index 438f02f..842596d 100644 (file)
@@ -86,10 +86,7 @@ static void spitz_discharge1(int on)
        gpio_set_value(SPITZ_GPIO_LED_GREEN, on);
 }
 
-static unsigned long gpio18_config[] = {
-       GPIO18_RDY,
-       GPIO18_GPIO,
-};
+static unsigned long gpio18_config = GPIO18_GPIO;
 
 static void spitz_presuspend(void)
 {
@@ -112,7 +109,7 @@ static void spitz_presuspend(void)
        PGSR3 &= ~SPITZ_GPIO_G3_STROBE_BIT;
        PGSR2 |= GPIO_bit(SPITZ_GPIO_KEY_STROBE0);
 
-       pxa2xx_mfp_config(&gpio18_config[0], 1);
+       pxa2xx_mfp_config(&gpio18_config, 1);
        gpio_request_one(18, GPIOF_OUT_INIT_HIGH, "Unknown");
        gpio_free(18);
 
@@ -131,7 +128,6 @@ static void spitz_presuspend(void)
 
 static void spitz_postsuspend(void)
 {
-       pxa2xx_mfp_config(&gpio18_config[1], 1);
 }
 
 static int spitz_should_wakeup(unsigned int resume_on_alarm)
index 749220f..4407b17 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 ed5a95e..77ee0b7 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 ab648ad..165b6a6 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 6e6a0a9..111e404 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 6219086..cc6e561 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 4c9e902..a0c50ef 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 2912eab..3cc8b1c 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));
index 3cafb6a..37b2a31 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.
index 2917668..ebbffc2 100644 (file)
@@ -247,7 +247,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();
 
diff --git a/arch/arm/mach-spear13xx/include/mach/spear1310_misc_regs.h b/arch/arm/mach-spear13xx/include/mach/spear1310_misc_regs.h
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/arch/arm/mach-spear13xx/include/mach/spear1340_misc_regs.h b/arch/arm/mach-spear13xx/include/mach/spear1340_misc_regs.h
deleted file mode 100644 (file)
index e69de29..0000000
index 57e235f..aa5325c 100644 (file)
@@ -182,7 +182,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 e4a676d..5e92a81 100644 (file)
@@ -89,7 +89,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 f88e514..91fbe73 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 cc9b5fd..8d398a3 100644 (file)
@@ -953,6 +953,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 5cd502c..e9de5df 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 d92cb55..3d2e553 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 eccdce9..d3b8c8e 100644 (file)
@@ -245,7 +245,7 @@ static void __init tegra_init_timer(void)
        register_persistent_clock(NULL, tegra_read_persistent_clock);
 }
 
-struct sys_timer tegra_timer = {
+struct sys_timer tegra_sys_timer = {
        .init = tegra_init_timer,
 };
 
index b8efac4..ece8a2d 100644 (file)
@@ -1445,8 +1445,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,
 };
 
 static struct platform_device gpio_device = {
@@ -1590,6 +1588,7 @@ static struct platform_device *platform_devs[] __initdata = {
        &i2c1_device,
        &keypad_device,
        &rtc_device,
+       &pinctrl_device,
        &gpio_device,
        &nand_device,
        &wdog_device,
@@ -1804,7 +1803,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 e27425a..21d5e76 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 070629a..33631c9 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 a267c6d..c34d4ef 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 416d436..0a3dd60 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 bcdfe6b..91f028c 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"
@@ -158,7 +158,7 @@ static void __init db8500_add_gpios(struct device *parent)
 
        dbx500_add_gpios(parent, ARRAY_AND_SIZE(db8500_gpio_base),
                         IRQ_DB8500_GPIO0, &pdata);
-       dbx500_add_pinctrl(parent, "pinctrl-db8500");
+       dbx500_add_pinctrl(parent, "pinctrl-db8500", U8500_PRCMU_BASE);
 }
 
 static int usb_db8500_rx_dma_cfg[] = {
@@ -214,9 +214,6 @@ struct device * __init u8500_init_devices(struct ab8500_platform_data *ab8500)
        db8500_add_gpios(parent);
        db8500_add_usb(parent, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg);
 
-       platform_device_register_data(parent,
-               "cpufreq-u8500", -1, NULL, 0);
-
        for (i = 0; i < ARRAY_SIZE(platform_devs); i++)
                platform_devs[i]->dev.parent = parent;
 
@@ -236,9 +233,6 @@ struct device * __init u8500_of_init_devices(void)
 
        db8500_add_usb(parent, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg);
 
-       platform_device_register_data(parent,
-               "cpufreq-u8500", -1, NULL, 0);
-
        u8500_dma40_device.dev.parent = parent;
 
        /*
index 2236cbd..1f3fbc2 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/stat.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
+#include <linux/irq.h>
 #include <linux/platform_data/clk-ux500.h>
 
 #include <asm/hardware/gic.h>
index dfdd4a5..692a77a 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>
 
index 7fbf0ba..96fa4ac 100644 (file)
@@ -129,12 +129,18 @@ void dbx500_add_gpios(struct device *parent, resource_size_t *base, int num,
                      int irq, struct nmk_gpio_platform_data *pdata);
 
 static inline void
-dbx500_add_pinctrl(struct device *parent, const char *name)
+dbx500_add_pinctrl(struct device *parent, const char *name,
+                  resource_size_t base)
 {
+       struct resource res[] = {
+               DEFINE_RES_MEM(base, SZ_8K),
+       };
        struct platform_device_info pdevinfo = {
                .parent = parent,
                .name = name,
                .id = -1,
+               .res = res,
+               .num_res = ARRAY_SIZE(res),
        };
 
        platform_device_register_full(&pdevinfo);
index 560e0df..359f782 100644 (file)
@@ -589,7 +589,7 @@ void __init v2m_dt_init_early(void)
                return;
 
        /* Confirm board type against DT property, if available */
-       if (of_property_read_u32(allnodes, "arm,hbi", &dt_hbi) == 0) {
+       if (of_property_read_u32(of_allnodes, "arm,hbi", &dt_hbi) == 0) {
                int site = v2m_get_master_site();
                u32 id = readl(v2m_sysreg_base + (site == SYS_CFG_SITE_DB2 ?
                                V2M_SYS_PROCID1 : V2M_SYS_PROCID0));
index b9f60eb..b820eda 100644 (file)
@@ -745,7 +745,7 @@ do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs,
 static int
 do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 {
-       union offset_union offset;
+       union offset_union uninitialized_var(offset);
        unsigned long instr = 0, instrptr;
        int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs);
        unsigned int type;
@@ -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:
index 477a2d2..58bc3e4 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 86b8b48..09c5233 100644 (file)
@@ -89,7 +89,7 @@ ENTRY(cpu_v6_dcache_clean_area)
        mov     pc, lr
 
 /*
- *     cpu_arm926_switch_mm(pgd_phys, tsk)
+ *     cpu_v6_switch_mm(pgd_phys, tsk)
  *
  *     Set the translation table base pointer to be pgd_phys
  *
index bf312c3..0f5a5f2 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;
 };
index 540d3a7..e7b920b 100644 (file)
@@ -55,7 +55,7 @@ struct platform_device *__init imx_add_mxc_mmc(
        struct resource res[] = {
                {
                        .start = data->iobase,
-                       .end = data->iobase + SZ_4K - 1,
+                       .end = data->iobase + data->iosize - 1,
                        .flags = IORESOURCE_MEM,
                }, {
                        .start = data->irq,
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 7cd56ed..82fcb20 100644 (file)
@@ -26,6 +26,7 @@ config ARCH_OMAP2PLUS
        select CLKDEV_LOOKUP
        select GENERIC_IRQ_CHIP
        select OMAP_DM_TIMER
+       select PINCTRL
        select PROC_DEVICETREE if PROC_FS
        select SPARSE_IRQ
        select USE_OF
index c7a4c09..5a4678e 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 a5683a8..6013831 100644 (file)
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
+#include <linux/i2c-omap.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/clk.h>
 
 #include <mach/irqs.h>
 #include <plat/i2c.h>
+#include <plat/omap-pm.h>
 #include <plat/omap_device.h>
 
 #define OMAP_I2C_SIZE          0x3f
@@ -127,6 +129,16 @@ static inline int omap1_i2c_add_bus(int bus_id)
 
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
+/*
+ * XXX This function is a temporary compatibility wrapper - only
+ * needed until the I2C driver can be converted to call
+ * omap_pm_set_max_dev_wakeup_lat() and handle a return code.
+ */
+static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t)
+{
+       omap_pm_set_max_mpu_wakeup_lat(dev, t);
+}
+
 static inline int omap2_i2c_add_bus(int bus_id)
 {
        int l;
@@ -158,6 +170,15 @@ static inline int omap2_i2c_add_bus(int bus_id)
        dev_attr = (struct omap_i2c_dev_attr *)oh->dev_attr;
        pdata->flags = dev_attr->flags;
 
+       /*
+        * When waiting for completion of a i2c transfer, we need to
+        * set a wake up latency constraint for the MPU. This is to
+        * ensure quick enough wakeup from idle, when transfer
+        * completes.
+        * Only omap3 has support for constraints
+        */
+       if (cpu_is_omap34xx())
+               pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat;
        pdev = omap_device_build(name, bus_id, oh, pdata,
                        sizeof(struct omap_i2c_bus_platform_data),
                        NULL, 0, 0);
index 8b4e4f2..346af5b 100644 (file)
@@ -126,6 +126,7 @@ struct omap_mmc_platform_data {
                /* we can put the features above into this variable */
 #define HSMMC_HAS_PBIAS                (1 << 0)
 #define HSMMC_HAS_UPDATED_RESET        (1 << 1)
+#define HSMMC_HAS_HSPE_SUPPORT (1 << 2)
                unsigned features;
 
                int switch_pin;                 /* gpio (card detect) */
index f4a4cd0..1957a85 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 b3349f7..1db0294 100644 (file)
@@ -443,6 +443,11 @@ struct omap_hwmod_omap4_prcm {
  *     in order to complete the reset. Optional clocks will be disabled
  *     again after the reset.
  * HWMOD_16BIT_REG: Module has 16bit registers
+ * HWMOD_EXT_OPT_MAIN_CLK: The only main functional clock source for
+ *     this IP block comes from an off-chip source and is not always
+ *     enabled.  This prevents the hwmod code from being able to
+ *     enable and reset the IP block early.  XXX Eventually it should
+ *     be possible to query the clock framework for this information.
  */
 #define HWMOD_SWSUP_SIDLE                      (1 << 0)
 #define HWMOD_SWSUP_MSTANDBY                   (1 << 1)
@@ -453,6 +458,7 @@ struct omap_hwmod_omap4_prcm {
 #define HWMOD_NO_IDLEST                                (1 << 6)
 #define HWMOD_CONTROL_OPT_CLKS_IN_RESET                (1 << 7)
 #define HWMOD_16BIT_REG                                (1 << 8)
+#define HWMOD_EXT_OPT_MAIN_CLK                 (1 << 9)
 
 /*
  * omap_hwmod._int_flags definitions
index db98e70..0abd1c4 100644 (file)
@@ -473,12 +473,13 @@ int s3c2410_dma_enqueue(enum dma_ch channel, void *id,
                pr_debug("dma%d: %s: buffer %p queued onto non-empty channel\n",
                         chan->number, __func__, buf);
 
-               if (chan->end == NULL)
+               if (chan->end == NULL) {
                        pr_debug("dma%d: %s: %p not empty, and chan->end==NULL?\n",
                                 chan->number, __func__, chan);
-
-               chan->end->next = buf;
-               chan->end = buf;
+               } else {
+                       chan->end->next = buf;
+                       chan->end = buf;
+               }
        }
 
        /* if necessary, update the next buffer field */
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 635cb18..32d05c8 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 c834b32..3b44e0d 100644 (file)
@@ -701,11 +701,14 @@ static int __init vfp_init(void)
                        elf_hwcap |= HWCAP_VFPv3;
 
                        /*
-                        * Check for VFPv3 D16. CPUs in this configuration
-                        * only have 16 x 64bit registers.
+                        * Check for VFPv3 D16 and VFPv4 D16.  CPUs in
+                        * this configuration only have 16 x 64bit
+                        * registers.
                         */
                        if (((fmrx(MVFR0) & MVFR0_A_SIMD_MASK)) == 1)
-                               elf_hwcap |= HWCAP_VFPv3D16;
+                               elf_hwcap |= HWCAP_VFPv3D16; /* also v4-D16 */
+                       else
+                               elf_hwcap |= HWCAP_VFPD32;
                }
 #endif
                /*
index 59bcb96..f576092 100644 (file)
@@ -166,3 +166,14 @@ void free_xenballooned_pages(int nr_pages, struct page **pages)
        *pages = NULL;
 }
 EXPORT_SYMBOL_GPL(free_xenballooned_pages);
+
+/* In the hypervisor.S file. */
+EXPORT_SYMBOL_GPL(HYPERVISOR_event_channel_op);
+EXPORT_SYMBOL_GPL(HYPERVISOR_grant_table_op);
+EXPORT_SYMBOL_GPL(HYPERVISOR_xen_version);
+EXPORT_SYMBOL_GPL(HYPERVISOR_console_io);
+EXPORT_SYMBOL_GPL(HYPERVISOR_sched_op);
+EXPORT_SYMBOL_GPL(HYPERVISOR_hvm_op);
+EXPORT_SYMBOL_GPL(HYPERVISOR_memory_op);
+EXPORT_SYMBOL_GPL(HYPERVISOR_physdev_op);
+EXPORT_SYMBOL_GPL(privcmd_call);
index dbd1330..859a9bb 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 074f5ed..71f7239 100644 (file)
 
 #include <linux/linkage.h>
 #include <asm/assembler.h>
+#include <asm/opcodes-virt.h>
 #include <xen/interface/xen.h>
 
 
-/* HVC 0xEA1 */
-#ifdef CONFIG_THUMB2_KERNEL
-#define xen_hvc .word 0xf7e08ea1
-#else
-#define xen_hvc .word 0xe140ea71
-#endif
+#define XEN_IMM 0xEA1
 
 #define HYPERCALL_SIMPLE(hypercall)            \
 ENTRY(HYPERVISOR_##hypercall)                  \
        mov r12, #__HYPERVISOR_##hypercall;     \
-       xen_hvc;                                                        \
+       __HVC(XEN_IMM);                                         \
        mov pc, lr;                                                     \
 ENDPROC(HYPERVISOR_##hypercall)
 
@@ -76,7 +72,7 @@ ENTRY(HYPERVISOR_##hypercall)                 \
        stmdb sp!, {r4}                                         \
        ldr r4, [sp, #4]                                        \
        mov r12, #__HYPERVISOR_##hypercall;     \
-       xen_hvc                                                         \
+       __HVC(XEN_IMM);                                         \
        ldm sp!, {r4}                                           \
        mov pc, lr                                                      \
 ENDPROC(HYPERVISOR_##hypercall)
@@ -100,7 +96,7 @@ ENTRY(privcmd_call)
        mov r2, r3
        ldr r3, [sp, #8]
        ldr r4, [sp, #4]
-       xen_hvc
+       __HVC(XEN_IMM)
        ldm sp!, {r4}
        mov pc, lr
 ENDPROC(privcmd_call);
index 7ff68c9..15ac18a 100644 (file)
@@ -1,6 +1,7 @@
 config ARM64
        def_bool y
        select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
+       select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
        select GENERIC_CLOCKEVENTS
        select GENERIC_HARDIRQS_NO_DEPRECATED
        select GENERIC_IOMAP
@@ -22,6 +23,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 364191f..c95c5cb 100644 (file)
@@ -41,20 +41,24 @@ libs-y              := arch/arm64/lib/ $(libs-y)
 libs-y         += $(LIBGCC)
 
 # Default target when executing plain make
-KBUILD_IMAGE := Image.gz
+KBUILD_IMAGE   := Image.gz
+KBUILD_DTBS    := dtbs
 
-all:   $(KBUILD_IMAGE)
+all:   $(KBUILD_IMAGE) $(KBUILD_DTBS)
 
 boot := arch/arm64/boot
 
 Image Image.gz: vmlinux
-       $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
+       $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
 zinstall install: vmlinux
-       $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
+       $(Q)$(MAKE) $(build)=$(boot) $@
 
-%.dtb:
-       $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
+%.dtb: scripts
+       $(Q)$(MAKE) $(build)=$(boot)/dts $(boot)/dts/$@
+
+dtbs: scripts
+       $(Q)$(MAKE) $(build)=$(boot)/dts dtbs
 
 # We use MRPROPER_FILES and CLEAN_FILES now
 archclean:
@@ -63,6 +67,7 @@ archclean:
 define archhelp
   echo  '* Image.gz      - Compressed kernel image (arch/$(ARCH)/boot/Image.gz)'
   echo  '  Image         - Uncompressed kernel image (arch/$(ARCH)/boot/Image)'
+  echo  '* dtbs          - Build device tree blobs for enabled boards'
   echo  '  install       - Install uncompressed kernel'
   echo  '  zinstall      - Install compressed kernel'
   echo  '                  Install using (your) ~/bin/installkernel or'
index eca209b..5a0e3ab 100644 (file)
@@ -22,9 +22,6 @@ $(obj)/Image: vmlinux FORCE
 $(obj)/Image.gz: $(obj)/Image FORCE
        $(call if_changed,gzip)
 
-$(obj)/%.dtb: $(src)/dts/%.dts
-       $(call cmd,dtc)
-
 install: $(obj)/Image
        $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
        $(obj)/Image System.map "$(INSTALL_PATH)"
@@ -32,5 +29,3 @@ install: $(obj)/Image
 zinstall: $(obj)/Image.gz
        $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
        $(obj)/Image.gz System.map "$(INSTALL_PATH)"
-
-clean-files += *.dtb
diff --git a/arch/arm64/boot/dts/.gitignore b/arch/arm64/boot/dts/.gitignore
new file mode 100644 (file)
index 0000000..b60ed20
--- /dev/null
@@ -0,0 +1 @@
+*.dtb
diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
new file mode 100644 (file)
index 0000000..801e2d7
--- /dev/null
@@ -0,0 +1,5 @@
+targets += dtbs
+
+dtbs: $(addprefix $(obj)/, $(dtb-y))
+
+clean-files := *.dtb
index fe77e51..a581a22 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 cf28464..07fea29 100644 (file)
 #include <asm/user.h>
 
 typedef unsigned long elf_greg_t;
-typedef unsigned long elf_freg_t[3];
 
 #define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
 typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-typedef struct user_fp elf_fpregset_t;
+typedef struct user_fpsimd_state elf_fpregset_t;
 
 #define EM_AARCH64             183
 
@@ -87,7 +85,6 @@ typedef struct user_fp elf_fpregset_t;
 #define R_AARCH64_MOVW_PREL_G2_NC      292
 #define R_AARCH64_MOVW_PREL_G3         293
 
-
 /*
  * These are used to set parameters in the core dumps.
  */
index b42fab9..c43b4ac 100644 (file)
@@ -25,9 +25,8 @@
  *  - FPSR and FPCR
  *  - 32 128-bit data registers
  *
- * Note that user_fp forms a prefix of this structure, which is relied
- * upon in the ptrace FP/SIMD accessors. struct user_fpsimd_state must
- * form a prefix of struct fpsimd_state.
+ * Note that user_fpsimd forms a prefix of this structure, which is
+ * relied upon in the ptrace FP/SIMD accessors.
  */
 struct fpsimd_state {
        union {
index 74a2a7d..d2f05a6 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)
 {
@@ -222,12 +222,12 @@ extern void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot
 extern void __iounmap(volatile void __iomem *addr);
 
 #define PROT_DEFAULT           (PTE_TYPE_PAGE | PTE_AF | PTE_DIRTY)
-#define PROT_DEVICE_nGnRE      (PROT_DEFAULT | PTE_XN | PTE_ATTRINDX(MT_DEVICE_nGnRE))
+#define PROT_DEVICE_nGnRE      (PROT_DEFAULT | PTE_PXN | PTE_UXN | 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 0f3b458..75fd13d 100644 (file)
@@ -38,7 +38,8 @@
 #define PMD_SECT_S             (_AT(pmdval_t, 3) << 8)
 #define PMD_SECT_AF            (_AT(pmdval_t, 1) << 10)
 #define PMD_SECT_NG            (_AT(pmdval_t, 1) << 11)
-#define PMD_SECT_XN            (_AT(pmdval_t, 1) << 54)
+#define PMD_SECT_PXN           (_AT(pmdval_t, 1) << 53)
+#define PMD_SECT_UXN           (_AT(pmdval_t, 1) << 54)
 
 /*
  * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers).
@@ -57,7 +58,8 @@
 #define PTE_SHARED             (_AT(pteval_t, 3) << 8)         /* SH[1:0], inner shareable */
 #define PTE_AF                 (_AT(pteval_t, 1) << 10)        /* Access Flag */
 #define PTE_NG                 (_AT(pteval_t, 1) << 11)        /* nG */
-#define PTE_XN                 (_AT(pteval_t, 1) << 54)        /* XN */
+#define PTE_PXN                        (_AT(pteval_t, 1) << 53)        /* Privileged XN */
+#define PTE_UXN                        (_AT(pteval_t, 1) << 54)        /* User XN */
 
 /*
  * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers).
index 8960239..14aba2d 100644 (file)
@@ -62,23 +62,23 @@ extern pgprot_t pgprot_default;
 
 #define _MOD_PROT(p, b)        __pgprot(pgprot_val(p) | (b))
 
-#define PAGE_NONE              _MOD_PROT(pgprot_default, PTE_NG | PTE_XN | PTE_RDONLY)
-#define PAGE_SHARED            _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN)
-#define PAGE_SHARED_EXEC       _MOD_PROT(pgprot_default, PTE_USER | PTE_NG)
-#define PAGE_COPY              _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY)
-#define PAGE_COPY_EXEC         _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_RDONLY)
-#define PAGE_READONLY          _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY)
-#define PAGE_READONLY_EXEC     _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_RDONLY)
-#define PAGE_KERNEL            _MOD_PROT(pgprot_default, PTE_XN | PTE_DIRTY)
-#define PAGE_KERNEL_EXEC       _MOD_PROT(pgprot_default, PTE_DIRTY)
-
-#define __PAGE_NONE            __pgprot(_PAGE_DEFAULT | PTE_NG | PTE_XN | PTE_RDONLY)
-#define __PAGE_SHARED          __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN)
-#define __PAGE_SHARED_EXEC     __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG)
-#define __PAGE_COPY            __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY)
-#define __PAGE_COPY_EXEC       __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_RDONLY)
-#define __PAGE_READONLY                __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY)
-#define __PAGE_READONLY_EXEC   __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_RDONLY)
+#define PAGE_NONE              _MOD_PROT(pgprot_default, PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define PAGE_SHARED            _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
+#define PAGE_SHARED_EXEC       _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN)
+#define PAGE_COPY              _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define PAGE_COPY_EXEC         _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY)
+#define PAGE_READONLY          _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define PAGE_READONLY_EXEC     _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY)
+#define PAGE_KERNEL            _MOD_PROT(pgprot_default, PTE_PXN | PTE_UXN | PTE_DIRTY)
+#define PAGE_KERNEL_EXEC       _MOD_PROT(pgprot_default, PTE_UXN | PTE_DIRTY)
+
+#define __PAGE_NONE            __pgprot(_PAGE_DEFAULT | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define __PAGE_SHARED          __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
+#define __PAGE_SHARED_EXEC     __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN)
+#define __PAGE_COPY            __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define __PAGE_COPY_EXEC       __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY)
+#define __PAGE_READONLY                __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define __PAGE_READONLY_EXEC   __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY)
 
 #endif /* __ASSEMBLY__ */
 
@@ -130,10 +130,10 @@ extern struct page *empty_zero_page;
 #define pte_young(pte)         (pte_val(pte) & PTE_AF)
 #define pte_special(pte)       (pte_val(pte) & PTE_SPECIAL)
 #define pte_write(pte)         (!(pte_val(pte) & PTE_RDONLY))
-#define pte_exec(pte)          (!(pte_val(pte) & PTE_XN))
+#define pte_exec(pte)          (!(pte_val(pte) & PTE_UXN))
 
 #define pte_present_exec_user(pte) \
-       ((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_XN)) == \
+       ((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_UXN)) == \
         (PTE_VALID | PTE_USER))
 
 #define PTE_BIT_FUNC(fn,op) \
@@ -262,7 +262,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
 
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
-       const pteval_t mask = PTE_USER | PTE_XN | PTE_RDONLY;
+       const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY;
        pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
        return pte;
 }
index 39a208a..77f696c 100644 (file)
@@ -43,6 +43,8 @@
 #else
 #define STACK_TOP              STACK_TOP_MAX
 #endif /* CONFIG_COMPAT */
+
+#define ARCH_LOW_ADDRESS_LIMIT PHYS_MASK
 #endif /* __KERNEL__ */
 
 struct debug_info {
@@ -92,30 +94,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 63f853f..68aff28 100644 (file)
@@ -14,7 +14,6 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 #ifdef CONFIG_COMPAT
-#define __ARCH_WANT_COMPAT_IPC_PARSE_VERSION
 #define __ARCH_WANT_COMPAT_STAT64
 #define __ARCH_WANT_SYS_GETHOSTNAME
 #define __ARCH_WANT_SYS_PAUSE
index 6d909fa..656a6f2 100644 (file)
@@ -392,7 +392,7 @@ __SYSCALL(367, sys_fanotify_init)
 __SYSCALL(368, compat_sys_fanotify_mark_wrapper)
 __SYSCALL(369, sys_prlimit64)
 __SYSCALL(370, sys_name_to_handle_at)
-__SYSCALL(371, sys_open_by_handle_at)
+__SYSCALL(371, compat_sys_open_by_handle_at)
 __SYSCALL(372, sys_clock_adjtime)
 __SYSCALL(373, sys_syncfs)
 
index 9b131b4..6913643 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 ecbf2d8..c76c724 100644 (file)
@@ -613,17 +613,11 @@ enum armv8_pmuv3_perf_types {
        ARMV8_PMUV3_PERFCTR_BUS_ACCESS                          = 0x19,
        ARMV8_PMUV3_PERFCTR_MEM_ERROR                           = 0x1A,
        ARMV8_PMUV3_PERFCTR_BUS_CYCLES                          = 0x1D,
-
-       /*
-        * This isn't an architected event.
-        * We detect this event number and use the cycle counter instead.
-        */
-       ARMV8_PMUV3_PERFCTR_CPU_CYCLES                          = 0xFF,
 };
 
 /* PMUv3 HW events mapping. */
 static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = {
-       [PERF_COUNT_HW_CPU_CYCLES]              = ARMV8_PMUV3_PERFCTR_CPU_CYCLES,
+       [PERF_COUNT_HW_CPU_CYCLES]              = ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES,
        [PERF_COUNT_HW_INSTRUCTIONS]            = ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED,
        [PERF_COUNT_HW_CACHE_REFERENCES]        = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
        [PERF_COUNT_HW_CACHE_MISSES]            = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
@@ -1106,7 +1100,7 @@ static int armv8pmu_get_event_idx(struct pmu_hw_events *cpuc,
        unsigned long evtype = event->config_base & ARMV8_EVTYPE_EVENT;
 
        /* Always place a cycle counter into the cycle counter. */
-       if (evtype == ARMV8_PMUV3_PERFCTR_CPU_CYCLES) {
+       if (evtype == ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES) {
                if (test_and_set_bit(ARMV8_IDX_CYCLE_COUNTER, cpuc->used_mask))
                        return -EAGAIN;
 
index f22965e..e04cebd 100644 (file)
@@ -310,24 +310,6 @@ struct task_struct *__switch_to(struct task_struct *prev,
 }
 
 /*
- * Fill in the task's elfregs structure for a core dump.
- */
-int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs)
-{
-       elf_core_copy_regs(elfregs, task_pt_regs(t));
-       return 1;
-}
-
-/*
- * fill in the fpe structure for a core dump...
- */
-int dump_fpu (struct pt_regs *regs, struct user_fp *fp)
-{
-       return 0;
-}
-EXPORT_SYMBOL(dump_fpu);
-
-/*
  * Shuffle the argument into the correct register before calling the
  * thread function.  x1 is the thread argument, x2 is the pointer to
  * the thread function, and x3 points to the exit function.
index 2ea3968..6e1e77f 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 48ffb9f..7665a9b 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 b711525..538300f 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
@@ -212,8 +211,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
         * before we continue.
         */
        set_cpu_online(cpu, true);
-       while (!cpu_active(cpu))
-               cpu_relax();
+       complete(&cpu_running);
 
        /*
         * OK, it's off to the idle thread for us
index 17948fc..ba45794 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 efbf7df..4cd2893 100644 (file)
@@ -80,7 +80,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
 #ifdef CONFIG_ZONE_DMA32
        /* 4GB maximum for 32-bit only capable devices */
        max_dma32 = min(max, MAX_DMA32_PFN);
-       zone_size[ZONE_DMA32] = max_dma32 - min;
+       zone_size[ZONE_DMA32] = max(min, max_dma32) - min;
 #endif
        zone_size[ZONE_NORMAL] = max - max_dma32;
 
index a9eb959..e72eb34 100644 (file)
@@ -41,7 +41,7 @@ DTB:=$(subst dtbImage.,,$(filter dtbImage.%, $(MAKECMDGOALS)))
 export DTB
 
 ifneq ($(DTB),)
-core-y += $(boot)/
+core-y += $(boot)/dts/
 endif
 
 # With make 3.82 we cannot mix normal and wildcard targets
index 6891257..8734abe 100644 (file)
@@ -6,25 +6,5 @@ OBJCOPYFLAGS_vmlinux.bin := -O binary
 $(obj)/vmlinux.bin: vmlinux FORCE
        $(call if_changed,objcopy)
 
-DTC_FLAGS ?= -p 1024
-
-ifneq ($(DTB),)
-obj-y += linked_dtb.o
-endif
-
-$(obj)/%.dtb: $(src)/dts/%.dts FORCE
-       $(call if_changed_dep,dtc)
-
-quiet_cmd_cp = CP      $< $@$2
-       cmd_cp = cat $< >$@$2 || (rm -f $@ && echo false)
-
-# Generate builtin.dtb from $(DTB).dtb
-$(obj)/builtin.dtb: $(obj)/$(DTB).dtb
-       $(call if_changed,cp)
-
-$(obj)/linked_dtb.o: $(obj)/builtin.dtb
-
 $(obj)/dtbImage.%: vmlinux
        $(call if_changed,objcopy)
-
-clean-files := $(obj)/*.dtb
diff --git a/arch/c6x/boot/dts/Makefile b/arch/c6x/boot/dts/Makefile
new file mode 100644 (file)
index 0000000..c7528b0
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# Makefile for device trees
+#
+
+DTC_FLAGS ?= -p 1024
+
+ifneq ($(DTB),)
+obj-y += linked_dtb.o
+endif
+
+quiet_cmd_cp = CP      $< $@$2
+       cmd_cp = cat $< >$@$2 || (rm -f $@ && echo false)
+
+# Generate builtin.dtb from $(DTB).dtb
+$(obj)/builtin.dtb: $(obj)/$(DTB).dtb
+       $(call if_changed,cp)
+
+$(obj)/linked_dtb.o: $(obj)/builtin.dtb
+
+clean-files := *.dtb
diff --git a/arch/c6x/boot/dts/linked_dtb.S b/arch/c6x/boot/dts/linked_dtb.S
new file mode 100644 (file)
index 0000000..cf347f1
--- /dev/null
@@ -0,0 +1,2 @@
+.section __fdt_blob,"a"
+.incbin "arch/c6x/boot/dts/builtin.dtb"
diff --git a/arch/c6x/boot/linked_dtb.S b/arch/c6x/boot/linked_dtb.S
deleted file mode 100644 (file)
index 57a4454..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-.section __fdt_blob,"a"
-.incbin "arch/c6x/boot/builtin.dtb"
diff --git a/arch/c6x/include/asm/setup.h b/arch/c6x/include/asm/setup.h
new file mode 100644 (file)
index 0000000..ecead15
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  Port on Texas Instruments TMS320C6x architecture
+ *
+ *  Copyright (C) 2004, 2009, 2010 2011 Texas Instruments Incorporated
+ *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.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 _ASM_C6X_SETUP_H
+#define _ASM_C6X_SETUP_H
+
+#include <uapi/asm/setup.h>
+
+#ifndef __ASSEMBLY__
+extern char c6x_command_line[COMMAND_LINE_SIZE];
+
+extern int c6x_add_memory(phys_addr_t start, unsigned long size);
+
+extern unsigned long ram_start;
+extern unsigned long ram_end;
+
+extern int c6x_num_cores;
+extern unsigned int c6x_silicon_rev;
+extern unsigned int c6x_devstat;
+extern unsigned char c6x_fuse_mac[6];
+
+extern void machine_init(unsigned long dt_ptr);
+extern void time_init(void);
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASM_C6X_SETUP_H */
index c312b42..e9bc2b2 100644 (file)
@@ -1,6 +1,8 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+generic-y += kvm_para.h
+
 header-y += byteorder.h
 header-y += kvm_para.h
 header-y += ptrace.h
diff --git a/arch/c6x/include/uapi/asm/kvm_para.h b/arch/c6x/include/uapi/asm/kvm_para.h
deleted file mode 100644 (file)
index 14fab8f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kvm_para.h>
index a01e318..ad9ac97 100644 (file)
@@ -1,33 +1,6 @@
-/*
- *  Port on Texas Instruments TMS320C6x architecture
- *
- *  Copyright (C) 2004, 2009, 2010 2011 Texas Instruments Incorporated
- *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.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 _ASM_C6X_SETUP_H
-#define _ASM_C6X_SETUP_H
+#ifndef _UAPI_ASM_C6X_SETUP_H
+#define _UAPI_ASM_C6X_SETUP_H
 
 #define COMMAND_LINE_SIZE   1024
 
-#ifndef __ASSEMBLY__
-extern char c6x_command_line[COMMAND_LINE_SIZE];
-
-extern int c6x_add_memory(phys_addr_t start, unsigned long size);
-
-extern unsigned long ram_start;
-extern unsigned long ram_end;
-
-extern int c6x_num_cores;
-extern unsigned int c6x_silicon_rev;
-extern unsigned int c6x_devstat;
-extern unsigned char c6x_fuse_mac[6];
-
-extern void machine_init(unsigned long dt_ptr);
-extern void time_init(void);
-
-#endif /* !__ASSEMBLY__ */
-#endif /* _ASM_C6X_SETUP_H */
+#endif /* _UAPI_ASM_C6X_SETUP_H */
index 5449c36..0ed6157 100644 (file)
@@ -277,6 +277,8 @@ work_rescheduled:
  [A1]  BNOP    .S1     work_resched,5
 
 work_notifysig:
+       ;; enable interrupts for do_notify_resume()
+       UNMASK_INT B2
        B       .S2     do_notify_resume
        LDW     .D2T1   *+SP(REGS__END+8),A6 ; syscall flag
        ADDKPC  .S2     resume_userspace,B3,1
@@ -427,8 +429,7 @@ ENTRY(ret_from_kernel_execve)
 ENDPROC(ret_from_kernel_execve)
 
        ;;
-       ;; These are the interrupt handlers, responsible for calling __do_IRQ()
-       ;; int6 is used for syscalls (see _system_call entry)
+       ;; These are the interrupt handlers, responsible for calling c6x_do_IRQ()
        ;;
        .macro SAVE_ALL_INT
        SAVE_ALL IRP,ITSR
index b741250..df2eb4b 100644 (file)
@@ -13,6 +13,7 @@ config FRV
        select GENERIC_CPU_DEVICES
        select ARCH_WANT_IPC_PARSE_VERSION
        select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
 
 config ZONE_DMA
        bool
index 6ae3254..636d5bb 100644 (file)
@@ -17,6 +17,8 @@ PARAMS_PHYS    = 0x0207c000
 INITRD_PHYS     = 0x02180000
 INITRD_VIRT     = 0x02180000
 
+OBJCOPYFLAGS   :=-O binary -R .note -R .note.gnu.build-id -R .comment
+
 #
 # If you don't define ZRELADDR above,
 # then it defaults to ZTEXTADDR
@@ -32,18 +34,18 @@ Image: $(obj)/Image
 targets: $(obj)/Image
 
 $(obj)/Image: vmlinux FORCE
-       $(OBJCOPY) -O binary -R .note -R .comment -S vmlinux $@
+       $(OBJCOPY) $(OBJCOPYFLAGS) -S vmlinux $@
 
 #$(obj)/Image: $(CONFIGURE) $(SYSTEM)
-#      $(OBJCOPY) -O binary -R .note -R .comment -g -S $(SYSTEM) $@
+#      $(OBJCOPY) $(OBJCOPYFLAGS) -g -S $(SYSTEM) $@
 
 bzImage: zImage
 
 zImage:        $(CONFIGURE) compressed/$(LINUX)
-       $(OBJCOPY) -O binary -R .note -R .comment -S compressed/$(LINUX) $@
+       $(OBJCOPY) $(OBJCOPYFLAGS) -S compressed/$(LINUX) $@
 
 bootpImage: bootp/bootp
-       $(OBJCOPY) -O binary -R .note -R .comment -S bootp/bootp $@
+       $(OBJCOPY) $(OBJCOPYFLAGS) -S bootp/bootp $@
 
 compressed/$(LINUX): $(LINUX) dep
        @$(MAKE) -C compressed $(LINUX)
index 266a5b2..2358634 100644 (file)
@@ -30,7 +30,6 @@
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
 #define __ARCH_WANT_SYS_EXECVE
-#define __ARCH_WANT_KERNEL_EXECVE
 
 /*
  * "Conditional" syscalls
index 0027329..dfcd263 100644 (file)
@@ -867,13 +867,8 @@ ret_from_fork:
 ret_from_kernel_thread:
        lddi.p          @(gr28,#REG_GR(8)),gr20
        call            schedule_tail
-       or.p            gr20,gr20,gr8
-       calll           @(gr21,gr0)
-       bra             sys_exit
-
-       .globl          ret_from_kernel_execve
-ret_from_kernel_execve:
-       ori             gr28,0,sp
+       calll.p         @(gr21,gr0)
+       or              gr20,gr20,gr8
        bra             __syscall_exit
 
 ###################################################################################################
@@ -1080,27 +1075,10 @@ __entry_return_from_kernel_interrupt:
        subicc          gr5,#0,gr0,icc0
        beq             icc0,#0,__entry_return_direct
 
-__entry_preempt_need_resched:
-       ldi             @(gr15,#TI_FLAGS),gr4
-       andicc          gr4,#_TIF_NEED_RESCHED,gr0,icc0
-       beq             icc0,#1,__entry_return_direct
-
-       setlos          #PREEMPT_ACTIVE,gr5
-       sti             gr5,@(gr15,#TI_FLAGS)
-
-       andi            gr23,#~PSR_PIL,gr23
-       movgs           gr23,psr
-
-       call            schedule
-       sti             gr0,@(gr15,#TI_PRE_COUNT)
-
-       movsg           psr,gr23
-       ori             gr23,#PSR_PIL_14,gr23
-       movgs           gr23,psr
-       bra             __entry_preempt_need_resched
-#else
-       bra             __entry_return_direct
+       subcc           gr0,gr0,gr0,icc2                /* set Z and clear C */
+       call            preempt_schedule_irq
 #endif
+       bra             __entry_return_direct
 
 
 ###############################################################################
index 655d90d..7e33215 100644 (file)
@@ -181,6 +181,9 @@ int copy_thread(unsigned long clone_flags,
        childregs = (struct pt_regs *)
                (task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE);
 
+       /* set up the userspace frame (the only place that the USP is stored) */
+       *childregs = *__kernel_frame0_ptr;
+
        p->set_child_tid = p->clear_child_tid = NULL;
 
        p->thread.frame  = childregs;
@@ -191,10 +194,8 @@ int copy_thread(unsigned long clone_flags,
        p->thread.frame0 = childregs;
 
        if (unlikely(!regs)) {
-               memset(childregs, 0, sizeof(struct pt_regs));
                childregs->gr9 = usp; /* function */
                childregs->gr8 = arg;
-               chilregs->psr = PSR_S;
                p->thread.pc = (unsigned long) ret_from_kernel_thread;
                save_user_regs(p->thread.user);
                return 0;
index 1f1e5ef..b8993c8 100644 (file)
@@ -112,9 +112,11 @@ char __initdata redboot_command_line[COMMAND_LINE_SIZE];
 #ifdef CONFIG_PM
 #define __pminit
 #define __pminitdata
+#define __pminitconst
 #else
 #define __pminit __init
 #define __pminitdata __initdata
+#define __pminitconst __initconst
 #endif
 
 struct clock_cmode {
index e47857f..b99c2a7 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/types.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <linux/dma-mapping.h>
 #include <linux/list.h>
 #include <linux/pci.h>
index c635028..05887a1 100644 (file)
@@ -2,7 +2,8 @@
 #define __ARCH_H8300_CACHE_H
 
 /* bytes per L1 cache line */
-#define        L1_CACHE_BYTES  4
+#define        L1_CACHE_SHIFT  2
+#define        L1_CACHE_BYTES  (1 << L1_CACHE_SHIFT)
 
 /* m68k-elf-gcc  2.95.2 doesn't like these */
 
index 3364b69..3bfa9b3 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 3e25804..468fbb0 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 a4ed6e2..1041a8e 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 4caa649..9b1e4af 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 0f01de2..f4ca594 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 6865c1b..49e0896 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 3ce4ecd..46ec8a7 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 c5f9527..9e78029 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 9ab12e9..5307971 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 233ed3d..85e9935 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 da6d2f6..9e34ff4 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 82b4996..1ba4b3b 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 350e6d4..c32b213 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 b27f494..b75b6bf 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 182cb9d..c144bee 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 1c02186..ca58773 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 b3acc2c..e527cfe 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 ded8c15..51661db 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 ec15236..e5fd949 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 9e87797..32a6fb6 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
diff --git a/arch/hexagon/include/asm/kvm_para.h b/arch/hexagon/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 a00b85f..31b4cbe 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 72e5dcd..af16e97 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 30a5d8d..2288b19 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 b4fe5a5..d423d2e 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 72ba494..6b4323a 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 edd9762..692adc2 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 8b8526b..430978b 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 13443c7..679bf6d 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 ca619bf..20d55f6 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 e8ea459..a03323a 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 87c869a..2b9b974 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 168a920..12ca4eb 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 99b5a75..7a906b5 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 f4489c1..7d37f47 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 089dd82..18b44b5 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 28ca0df..96745e7 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 3e7d61d..fb0e9d4 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 e4a0aad..f7c3240 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 081b82c..deda170 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 d80db23..79912b8 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 b11c62b..f63fe13 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 473abde..2f00772 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 b89a902..62d95a9 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 6a407f6..ec11285 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 7e706ea..e4127e4 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 2d95cbb..ed08e6c 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 cacda36..9b0e9c5 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 580462d..9a94de7 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 baebb3d..c31706c 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 2701cae..4a65815 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 0e19b9f..e31f3f7 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 285344b..5cec8c0 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 3d2f607..8ef7840 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 4dd741b..c20406f 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 3b754c5..e48285e 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 ce6dcd9..b6ba536 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 471c056..9395568 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 99cf0be..9069e92 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 c0d5565..81312d6 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 3a55078..cef13ee 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 89ffa51..2d5e84d 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 2b48751..65c7bdc 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 8e6b819..d859402 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 7f18924..32b1379 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 d4416a1..85883e1 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 fe4aa1b..3446453 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 61a76ba..477d07a 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 af51de6..9f6d741 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 96c3b2c..670b1b0 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 4d72fc5..6aeabc9 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 1202f78..94a3878 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 1ea16be..5047b8b 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 149fbef..8e095df 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 11c597b..f94918b 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 25a9bfe..319fa64 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 c550f41..7024b1d 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 36ba641..9903fad 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 ba44751..352f27e 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 06c36c0..18110a9 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 f08857d..a41eeb8 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 5d39f42..0bf5a87 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 5b99066..cd71673 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 591fc1b..9b5a4a2 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 aebb35b..80967f2 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 24d7fca..9fb77b3 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 0decf2f..62c6df9 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 97a4b50..620f42c 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 071d3c3..14e793f 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 9300552..8169f78 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 8ae47ba..885c962 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 2101c33..81c561c 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 26d9614..9341889 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 c5cf6ee..fe14ccf 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 8eb1d4d..7fc94f3 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 cb9740e..0cfbcc0 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 08d7d7b..254d8cc 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 b57d741..69ffcfd 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 3a37bc3..5905fd5 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 b175e2d..19760a4 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 5c6a16c..0eecb7a 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 e748108..3412726 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 513b74c..308ef0c 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 c6ff415..9647d00 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 4a159da..dd02f09 100644 (file)
@@ -1,3 +1,4 @@
 
 generic-y += clkdev.h
 generic-y += exec.h
+generic-y += kvm_para.h
index d05e78f..f69c32f 100644 (file)
@@ -7,9 +7,6 @@
 #define _ASM_IA64_DEVICE_H
 
 struct dev_archdata {
-#ifdef CONFIG_ACPI
-       void    *acpi_handle;
-#endif
 #ifdef CONFIG_INTEL_IOMMU
        void *iommu; /* hook for IOMMU specific extension */
 #endif
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 30cafac..1b3f5eb 100644 (file)
@@ -1,6 +1,8 @@
 # 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 += break.h
diff --git a/arch/ia64/include/uapi/asm/kvm_para.h b/arch/ia64/include/uapi/asm/kvm_para.h
deleted file mode 100644 (file)
index e69de29..0000000
index 4405788..e9682f5 100644 (file)
@@ -633,6 +633,7 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int triggering, int polarity)
                                      ACPI_EDGE_SENSITIVE) ? IOSAPIC_EDGE :
                                     IOSAPIC_LEVEL);
 }
+EXPORT_SYMBOL_GPL(acpi_register_gsi);
 
 void acpi_unregister_gsi(u32 gsi)
 {
@@ -644,6 +645,7 @@ void acpi_unregister_gsi(u32 gsi)
 
        iosapic_unregister_intr(gsi);
 }
+EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
 
 static int __init acpi_parse_fadt(struct acpi_table_header *table)
 {
index acd5b68..082e383 100644 (file)
@@ -637,7 +637,6 @@ mem_init (void)
 
        high_memory = __va(max_low_pfn * PAGE_SIZE);
 
-       reset_zone_present_pages();
        for_each_online_pgdat(pgdat)
                if (pgdat->bdata->node_bootmem_map)
                        totalram_pages += free_all_bootmem_node(pgdat);
index ecb5408..88fa3ac 100644 (file)
@@ -1,5 +1,3 @@
-include include/asm-generic/Kbuild.asm
-header-y += cachectl.h
 
 generic-y += bitsperlong.h
 generic-y += clkdev.h
index 5e08b59..0f71704 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 */
index 00c2c53..65e78a2 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 */
index 60e8866..2df26b5 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
@@ -156,7 +41,7 @@ typedef struct sigaltstack {
 static inline void sigaddset(sigset_t *set, int _sig)
 {
        asm ("bfset %0{%1,#1}"
-               : "+od" (*set)
+               : "+o" (*set)
                : "id" ((_sig - 1) ^ 31)
                : "cc");
 }
@@ -164,7 +49,7 @@ static inline void sigaddset(sigset_t *set, int _sig)
 static inline void sigdelset(sigset_t *set, int _sig)
 {
        asm ("bfclr %0{%1,#1}"
-               : "+od" (*set)
+               : "+o" (*set)
                : "id" ((_sig - 1) ^ 31)
                : "cc");
 }
@@ -180,7 +65,7 @@ static inline int __gen_sigismember(sigset_t *set, int _sig)
        int ret;
        asm ("bfextu %1{%2,#1},%0"
                : "=d" (ret)
-               : "od" (*set), "id" ((_sig-1) ^ 31)
+               : "o" (*set), "id" ((_sig-1) ^ 31)
                : "cc");
        return ret;
 }
@@ -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 */
index 0823032..ad8efb0 100644 (file)
@@ -1,27 +1,8 @@
 #ifndef _M68K_TERMIOS_H
 #define _M68K_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 */
-};
-
-#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
@@ -29,27 +10,6 @@ struct termio {
        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.
@@ -87,6 +47,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 /* _M68K_TERMIOS_H */
index c702ad7..5fc7f7b 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 baebb3d..972bce1 100644 (file)
@@ -1,3 +1,26 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += a.out.h
+header-y += auxvec.h
+header-y += byteorder.h
+header-y += cachectl.h
+header-y += fcntl.h
+header-y += ioctls.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 += termios.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 ce827b3..4fc2e29 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
 
index b23c40e..d26fb90 100644 (file)
@@ -57,7 +57,7 @@ boot := arch/microblaze/boot
 DTB:=$(subst simpleImage.,,$(filter simpleImage.%, $(MAKECMDGOALS)))
 
 ifneq ($(DTB),)
-       core-y  += $(boot)/
+       core-y  += $(boot)/dts/
 endif
 
 # defines filename extension depending memory management type
index fa83ea4..80fe54f 100644 (file)
@@ -2,21 +2,10 @@
 # arch/microblaze/boot/Makefile
 #
 
-obj-y += linked_dtb.o
-
 targets := linux.bin linux.bin.gz simpleImage.%
 
 OBJCOPYFLAGS := -R .note -R .comment -R .note.gnu.build-id -O binary
 
-# Ensure system.dtb exists
-$(obj)/linked_dtb.o: $(obj)/system.dtb
-
-# Generate system.dtb from $(DTB).dtb
-ifneq ($(DTB),system)
-$(obj)/system.dtb: $(obj)/$(DTB).dtb
-       $(call if_changed,cp)
-endif
-
 $(obj)/linux.bin: vmlinux FORCE
        $(call if_changed,objcopy)
        $(call if_changed,uimage)
@@ -45,10 +34,4 @@ $(obj)/simpleImage.%: vmlinux FORCE
        @echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
 
 
-# Rule to build device tree blobs
-DTC_FLAGS := -p 1024
-
-$(obj)/%.dtb: $(src)/dts/%.dts FORCE
-       $(call if_changed_dep,dtc)
-
-clean-files += *.dtb simpleImage.*.unstrip linux.bin.ub
+clean-files += simpleImage.*.unstrip linux.bin.ub
diff --git a/arch/microblaze/boot/dts/Makefile b/arch/microblaze/boot/dts/Makefile
new file mode 100644 (file)
index 0000000..c3b3a5d
--- /dev/null
@@ -0,0 +1,22 @@
+#
+# arch/microblaze/boot/Makefile
+#
+
+obj-y += linked_dtb.o
+
+# Ensure system.dtb exists
+$(obj)/linked_dtb.o: $(obj)/system.dtb
+
+# Generate system.dtb from $(DTB).dtb
+ifneq ($(DTB),system)
+$(obj)/system.dtb: $(obj)/$(DTB).dtb
+       $(call if_changed,cp)
+endif
+
+quiet_cmd_cp = CP      $< $@$2
+       cmd_cp = cat $< >$@$2 || (rm -f $@ && echo false)
+
+# Rule to build device tree blobs
+DTC_FLAGS := -p 1024
+
+clean-files += *.dtb
diff --git a/arch/microblaze/boot/dts/linked_dtb.S b/arch/microblaze/boot/dts/linked_dtb.S
new file mode 100644 (file)
index 0000000..23345af
--- /dev/null
@@ -0,0 +1,2 @@
+.section __fdt_blob,"a"
+.incbin "arch/microblaze/boot/dts/system.dtb"
diff --git a/arch/microblaze/boot/linked_dtb.S b/arch/microblaze/boot/linked_dtb.S
deleted file mode 100644 (file)
index cb2b537..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-.section __fdt_blob,"a"
-.incbin "arch/microblaze/boot/system.dtb"
-
index 3847e5b..3903e3d 100644 (file)
@@ -111,7 +111,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
 
        /* It is more difficult to avoid calling this function than to
         call it and ignore errors. */
-       if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->r1))
+       if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->r1) == -EFAULT)
                goto badframe;
 
        return rval;
index bc96e29..6e927cf 100644 (file)
@@ -24,9 +24,6 @@ DTB_FILES = $(patsubst %.dts, %.dtb, $(DTS_FILES))
 
 obj-y += $(patsubst %.dts, %.dtb.o, $(DTS_FILES))
 
-$(obj)/%.dtb: $(src)/%.dts FORCE
-       $(call if_changed_dep,dtc)
-
 # Let's keep the .dtb files around in case we want to look at them.
 .SECONDARY:  $(addprefix $(obj)/, $(DTB_FILES))
 
index d38246e..9f883bf 100644 (file)
@@ -30,6 +30,7 @@
  * measurement, and debugging facilities.
  */
 
+#include <linux/irqflags.h>
 #include <asm/octeon/cvmx.h>
 #include <asm/octeon/cvmx-l2c.h>
 #include <asm/octeon/cvmx-spinlock.h>
index 7cf80ca..f9f5307 100644 (file)
@@ -11,6 +11,7 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/irqflags.h>
 
 #include <asm/bcache.h>
 
index 82ad35c..46ac73a 100644 (file)
@@ -14,7 +14,6 @@
 #endif
 
 #include <linux/compiler.h>
-#include <linux/irqflags.h>
 #include <linux/types.h>
 #include <asm/barrier.h>
 #include <asm/byteorder.h>             /* sigh ... */
 #define smp_mb__before_clear_bit()     smp_mb__before_llsc()
 #define smp_mb__after_clear_bit()      smp_llsc_mb()
 
+
+/*
+ * These are the "slower" versions of the functions and are in bitops.c.
+ * These functions call raw_local_irq_{save,restore}().
+ */
+void __mips_set_bit(unsigned long nr, volatile unsigned long *addr);
+void __mips_clear_bit(unsigned long nr, volatile unsigned long *addr);
+void __mips_change_bit(unsigned long nr, volatile unsigned long *addr);
+int __mips_test_and_set_bit(unsigned long nr,
+                           volatile unsigned long *addr);
+int __mips_test_and_set_bit_lock(unsigned long nr,
+                                volatile unsigned long *addr);
+int __mips_test_and_clear_bit(unsigned long nr,
+                             volatile unsigned long *addr);
+int __mips_test_and_change_bit(unsigned long nr,
+                              volatile unsigned long *addr);
+
+
 /*
  * set_bit - Atomically set a bit in memory
  * @nr: the bit to set
@@ -57,7 +74,7 @@
 static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 {
        unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
        unsigned long temp;
 
        if (kernel_uses_llsc && R10000_LLSC_WAR) {
@@ -92,17 +109,8 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
                        : "=&r" (temp), "+m" (*m)
                        : "ir" (1UL << bit));
                } while (unlikely(!temp));
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               *a |= mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               __mips_set_bit(nr, addr);
 }
 
 /*
@@ -118,7 +126,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
 {
        unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
        unsigned long temp;
 
        if (kernel_uses_llsc && R10000_LLSC_WAR) {
@@ -153,17 +161,8 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
                        : "=&r" (temp), "+m" (*m)
                        : "ir" (~(1UL << bit)));
                } while (unlikely(!temp));
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               *a &= ~mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               __mips_clear_bit(nr, addr);
 }
 
 /*
@@ -191,7 +190,7 @@ static inline void clear_bit_unlock(unsigned long nr, volatile unsigned long *ad
  */
 static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
 {
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
 
        if (kernel_uses_llsc && R10000_LLSC_WAR) {
                unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
@@ -220,17 +219,8 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
                        : "=&r" (temp), "+m" (*m)
                        : "ir" (1UL << bit));
                } while (unlikely(!temp));
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               *a ^= mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               __mips_change_bit(nr, addr);
 }
 
 /*
@@ -244,7 +234,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
 static inline int test_and_set_bit(unsigned long nr,
        volatile unsigned long *addr)
 {
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
        unsigned long res;
 
        smp_mb__before_llsc();
@@ -281,18 +271,8 @@ static inline int test_and_set_bit(unsigned long nr,
                } while (unlikely(!res));
 
                res = temp & (1UL << bit);
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               res = (mask & *a);
-               *a |= mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               res = __mips_test_and_set_bit(nr, addr);
 
        smp_llsc_mb();
 
@@ -310,7 +290,7 @@ static inline int test_and_set_bit(unsigned long nr,
 static inline int test_and_set_bit_lock(unsigned long nr,
        volatile unsigned long *addr)
 {
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
        unsigned long res;
 
        if (kernel_uses_llsc && R10000_LLSC_WAR) {
@@ -345,18 +325,8 @@ static inline int test_and_set_bit_lock(unsigned long nr,
                } while (unlikely(!res));
 
                res = temp & (1UL << bit);
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               res = (mask & *a);
-               *a |= mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               res = __mips_test_and_set_bit_lock(nr, addr);
 
        smp_llsc_mb();
 
@@ -373,7 +343,7 @@ static inline int test_and_set_bit_lock(unsigned long nr,
 static inline int test_and_clear_bit(unsigned long nr,
        volatile unsigned long *addr)
 {
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
        unsigned long res;
 
        smp_mb__before_llsc();
@@ -428,18 +398,8 @@ static inline int test_and_clear_bit(unsigned long nr,
                } while (unlikely(!res));
 
                res = temp & (1UL << bit);
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               res = (mask & *a);
-               *a &= ~mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               res = __mips_test_and_clear_bit(nr, addr);
 
        smp_llsc_mb();
 
@@ -457,7 +417,7 @@ static inline int test_and_clear_bit(unsigned long nr,
 static inline int test_and_change_bit(unsigned long nr,
        volatile unsigned long *addr)
 {
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
        unsigned long res;
 
        smp_mb__before_llsc();
@@ -494,18 +454,8 @@ static inline int test_and_change_bit(unsigned long nr,
                } while (unlikely(!res));
 
                res = temp & (1UL << bit);
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               res = (mask & *a);
-               *a ^= mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               res = __mips_test_and_change_bit(nr, addr);
 
        smp_llsc_mb();
 
index 58277e0..3c5d146 100644 (file)
@@ -290,7 +290,7 @@ struct compat_shmid64_ds {
 
 static inline int is_compat_task(void)
 {
-       return test_thread_flag(TIF_32BIT);
+       return test_thread_flag(TIF_32BIT_ADDR);
 }
 
 #endif /* _ASM_COMPAT_H */
index e7cd782..dc0a5f7 100644 (file)
@@ -13,9 +13,9 @@
 
 #include <linux/param.h>
 
-extern void __delay(unsigned int loops);
-extern void __ndelay(unsigned int ns);
-extern void __udelay(unsigned int us);
+extern void __delay(unsigned long loops);
+extern void __ndelay(unsigned long ns);
+extern void __udelay(unsigned long us);
 
 #define ndelay(ns) __ndelay(ns)
 #define udelay(us) __udelay(us)
index bd94946..ef99db9 100644 (file)
@@ -95,7 +95,17 @@ static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
                                             pte_t *ptep, pte_t pte,
                                             int dirty)
 {
-       return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
+       int changed = !pte_same(*ptep, pte);
+
+       if (changed) {
+               set_pte_at(vma->vm_mm, addr, ptep, pte);
+               /*
+                * There could be some standard sized pages in there,
+                * get them all.
+                */
+               flush_tlb_range(vma, addr, addr + HPAGE_SIZE);
+       }
+       return changed;
 }
 
 static inline pte_t huge_ptep_get(pte_t *ptep)
index 29d9c23..ff2e034 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/compiler.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/irqflags.h>
 
 #include <asm/addrspace.h>
 #include <asm/bug.h>
index 309cbcd..9f3384c 100644 (file)
 #include <linux/compiler.h>
 #include <asm/hazards.h>
 
-__asm__(
-       "       .macro  arch_local_irq_enable                           \n"
-       "       .set    push                                            \n"
-       "       .set    reorder                                         \n"
-       "       .set    noat                                            \n"
-#ifdef CONFIG_MIPS_MT_SMTC
-       "       mfc0    $1, $2, 1       # SMTC - clear TCStatus.IXMT    \n"
-       "       ori     $1, 0x400                                       \n"
-       "       xori    $1, 0x400                                       \n"
-       "       mtc0    $1, $2, 1                                       \n"
-#elif defined(CONFIG_CPU_MIPSR2)
-       "       ei                                                      \n"
-#else
-       "       mfc0    $1,$12                                          \n"
-       "       ori     $1,0x1f                                         \n"
-       "       xori    $1,0x1e                                         \n"
-       "       mtc0    $1,$12                                          \n"
-#endif
-       "       irq_enable_hazard                                       \n"
-       "       .set    pop                                             \n"
-       "       .endm");
+#if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_MIPS_MT_SMTC)
 
-extern void smtc_ipi_replay(void);
-
-static inline void arch_local_irq_enable(void)
-{
-#ifdef CONFIG_MIPS_MT_SMTC
-       /*
-        * SMTC kernel needs to do a software replay of queued
-        * IPIs, at the cost of call overhead on each local_irq_enable()
-        */
-       smtc_ipi_replay();
-#endif
-       __asm__ __volatile__(
-               "arch_local_irq_enable"
-               : /* no outputs */
-               : /* no inputs */
-               : "memory");
-}
-
-
-/*
- * For cli() we have to insert nops to make sure that the new value
- * has actually arrived in the status register before the end of this
- * macro.
- * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs
- * no nops at all.
- */
-/*
- * For TX49, operating only IE bit is not enough.
- *
- * If mfc0 $12 follows store and the mfc0 is last instruction of a
- * page and fetching the next instruction causes TLB miss, the result
- * of the mfc0 might wrongly contain EXL bit.
- *
- * ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008
- *
- * Workaround: mask EXL bit of the result or place a nop before mfc0.
- */
 __asm__(
        "       .macro  arch_local_irq_disable\n"
        "       .set    push                                            \n"
        "       .set    noat                                            \n"
-#ifdef CONFIG_MIPS_MT_SMTC
-       "       mfc0    $1, $2, 1                                       \n"
-       "       ori     $1, 0x400                                       \n"
-       "       .set    noreorder                                       \n"
-       "       mtc0    $1, $2, 1                                       \n"
-#elif defined(CONFIG_CPU_MIPSR2)
        "       di                                                      \n"
-#else
-       "       mfc0    $1,$12                                          \n"
-       "       ori     $1,0x1f                                         \n"
-       "       xori    $1,0x1f                                         \n"
-       "       .set    noreorder                                       \n"
-       "       mtc0    $1,$12                                          \n"
-#endif
        "       irq_disable_hazard                                      \n"
        "       .set    pop                                             \n"
        "       .endm                                                   \n");
@@ -106,46 +36,14 @@ static inline void arch_local_irq_disable(void)
                : "memory");
 }
 
-__asm__(
-       "       .macro  arch_local_save_flags flags                     \n"
-       "       .set    push                                            \n"
-       "       .set    reorder                                         \n"
-#ifdef CONFIG_MIPS_MT_SMTC
-       "       mfc0    \\flags, $2, 1                                  \n"
-#else
-       "       mfc0    \\flags, $12                                    \n"
-#endif
-       "       .set    pop                                             \n"
-       "       .endm                                                   \n");
-
-static inline unsigned long arch_local_save_flags(void)
-{
-       unsigned long flags;
-       asm volatile("arch_local_save_flags %0" : "=r" (flags));
-       return flags;
-}
 
 __asm__(
        "       .macro  arch_local_irq_save result                      \n"
        "       .set    push                                            \n"
        "       .set    reorder                                         \n"
        "       .set    noat                                            \n"
-#ifdef CONFIG_MIPS_MT_SMTC
-       "       mfc0    \\result, $2, 1                                 \n"
-       "       ori     $1, \\result, 0x400                             \n"
-       "       .set    noreorder                                       \n"
-       "       mtc0    $1, $2, 1                                       \n"
-       "       andi    \\result, \\result, 0x400                       \n"
-#elif defined(CONFIG_CPU_MIPSR2)
        "       di      \\result                                        \n"
        "       andi    \\result, 1                                     \n"
-#else
-       "       mfc0    \\result, $12                                   \n"
-       "       ori     $1, \\result, 0x1f                              \n"
-       "       xori    $1, 0x1f                                        \n"
-       "       .set    noreorder                                       \n"
-       "       mtc0    $1, $12                                         \n"
-#endif
        "       irq_disable_hazard                                      \n"
        "       .set    pop                                             \n"
        "       .endm                                                   \n");
@@ -160,61 +58,37 @@ static inline unsigned long arch_local_irq_save(void)
        return flags;
 }
 
+
 __asm__(
        "       .macro  arch_local_irq_restore flags                    \n"
        "       .set    push                                            \n"
        "       .set    noreorder                                       \n"
        "       .set    noat                                            \n"
-#ifdef CONFIG_MIPS_MT_SMTC
-       "mfc0   $1, $2, 1                                               \n"
-       "andi   \\flags, 0x400                                          \n"
-       "ori    $1, 0x400                                               \n"
-       "xori   $1, 0x400                                               \n"
-       "or     \\flags, $1                                             \n"
-       "mtc0   \\flags, $2, 1                                          \n"
-#elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
+#if defined(CONFIG_IRQ_CPU)
        /*
         * Slow, but doesn't suffer from a relatively unlikely race
         * condition we're having since days 1.
         */
        "       beqz    \\flags, 1f                                     \n"
-       "        di                                                     \n"
+       "       di                                                      \n"
        "       ei                                                      \n"
        "1:                                                             \n"
-#elif defined(CONFIG_CPU_MIPSR2)
+#else
        /*
         * Fast, dangerous.  Life is fun, life is good.
         */
        "       mfc0    $1, $12                                         \n"
        "       ins     $1, \\flags, 0, 1                               \n"
        "       mtc0    $1, $12                                         \n"
-#else
-       "       mfc0    $1, $12                                         \n"
-       "       andi    \\flags, 1                                      \n"
-       "       ori     $1, 0x1f                                        \n"
-       "       xori    $1, 0x1f                                        \n"
-       "       or      \\flags, $1                                     \n"
-       "       mtc0    \\flags, $12                                    \n"
 #endif
        "       irq_disable_hazard                                      \n"
        "       .set    pop                                             \n"
        "       .endm                                                   \n");
 
-
 static inline void arch_local_irq_restore(unsigned long flags)
 {
        unsigned long __tmp1;
 
-#ifdef CONFIG_MIPS_MT_SMTC
-       /*
-        * SMTC kernel needs to do a software replay of queued
-        * IPIs, at the cost of branch and call overhead on each
-        * local_irq_restore()
-        */
-       if (unlikely(!(flags & 0x0400)))
-               smtc_ipi_replay();
-#endif
-
        __asm__ __volatile__(
                "arch_local_irq_restore\t%0"
                : "=r" (__tmp1)
@@ -232,6 +106,75 @@ static inline void __arch_local_irq_restore(unsigned long flags)
                : "0" (flags)
                : "memory");
 }
+#else
+/* Functions that require preempt_{dis,en}able() are in mips-atomic.c */
+void arch_local_irq_disable(void);
+unsigned long arch_local_irq_save(void);
+void arch_local_irq_restore(unsigned long flags);
+void __arch_local_irq_restore(unsigned long flags);
+#endif /* if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_MIPS_MT_SMTC) */
+
+
+__asm__(
+       "       .macro  arch_local_irq_enable                           \n"
+       "       .set    push                                            \n"
+       "       .set    reorder                                         \n"
+       "       .set    noat                                            \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "       mfc0    $1, $2, 1       # SMTC - clear TCStatus.IXMT    \n"
+       "       ori     $1, 0x400                                       \n"
+       "       xori    $1, 0x400                                       \n"
+       "       mtc0    $1, $2, 1                                       \n"
+#elif defined(CONFIG_CPU_MIPSR2)
+       "       ei                                                      \n"
+#else
+       "       mfc0    $1,$12                                          \n"
+       "       ori     $1,0x1f                                         \n"
+       "       xori    $1,0x1e                                         \n"
+       "       mtc0    $1,$12                                          \n"
+#endif
+       "       irq_enable_hazard                                       \n"
+       "       .set    pop                                             \n"
+       "       .endm");
+
+extern void smtc_ipi_replay(void);
+
+static inline void arch_local_irq_enable(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+       /*
+        * SMTC kernel needs to do a software replay of queued
+        * IPIs, at the cost of call overhead on each local_irq_enable()
+        */
+       smtc_ipi_replay();
+#endif
+       __asm__ __volatile__(
+               "arch_local_irq_enable"
+               : /* no outputs */
+               : /* no inputs */
+               : "memory");
+}
+
+
+__asm__(
+       "       .macro  arch_local_save_flags flags                     \n"
+       "       .set    push                                            \n"
+       "       .set    reorder                                         \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "       mfc0    \\flags, $2, 1                                  \n"
+#else
+       "       mfc0    \\flags, $12                                    \n"
+#endif
+       "       .set    pop                                             \n"
+       "       .endm                                                   \n");
+
+static inline unsigned long arch_local_save_flags(void)
+{
+       unsigned long flags;
+       asm volatile("arch_local_save_flags %0" : "=r" (flags));
+       return flags;
+}
+
 
 static inline int arch_irqs_disabled_flags(unsigned long flags)
 {
@@ -245,7 +188,7 @@ static inline int arch_irqs_disabled_flags(unsigned long flags)
 #endif
 }
 
-#endif
+#endif /* #ifndef __ASSEMBLY__ */
 
 /*
  * Do the CPU's IRQ-state tracing from assembly code.
index c26e182..f5b521d 100644 (file)
@@ -9,6 +9,7 @@
 #ifndef _ASM_PGTABLE_64_H
 #define _ASM_PGTABLE_64_H
 
+#include <linux/compiler.h>
 #include <linux/linkage.h>
 
 #include <asm/addrspace.h>
@@ -172,7 +173,19 @@ static inline int pmd_none(pmd_t pmd)
        return pmd_val(pmd) == (unsigned long) invalid_pte_table;
 }
 
-#define pmd_bad(pmd)           (pmd_val(pmd) & ~PAGE_MASK)
+static inline int pmd_bad(pmd_t pmd)
+{
+#ifdef CONFIG_HUGETLB_PAGE
+       /* pmd_huge(pmd) but inline */
+       if (unlikely(pmd_val(pmd) & _PAGE_HUGE))
+               return 0;
+#endif
+
+       if (unlikely(pmd_val(pmd) & ~PAGE_MASK))
+               return 1;
+
+       return 0;
+}
 
 static inline int pmd_present(pmd_t pmd)
 {
index 8debe9e..18806a5 100644 (file)
@@ -112,12 +112,6 @@ register struct thread_info *__current_thread_info __asm__("$28");
 #define TIF_LOAD_WATCH         25      /* If set, load watch registers */
 #define TIF_SYSCALL_TRACE      31      /* syscall trace active */
 
-#ifdef CONFIG_MIPS32_O32
-#define TIF_32BIT TIF_32BIT_REGS
-#elif defined(CONFIG_MIPS32_N32)
-#define TIF_32BIT _TIF_32BIT_ADDR
-#endif /* CONFIG_MIPS32_O32 */
-
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
index b9fe3ad..8eb715b 100644 (file)
@@ -14,6 +14,9 @@
  */
 
 #ifndef __MIPS_JZ4740_SERIAL_H__
+#define __MIPS_JZ4740_SERIAL_H__
+
+struct uart_port;
 
 void jz4740_serial_out(struct uart_port *p, int offset, int value);
 
index b1fb7af..cce3782 100644 (file)
@@ -510,7 +510,6 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
                                c->cputype = CPU_R3000A;
                                __cpu_name[cpu] = "R3000A";
                        }
-                       break;
                } else {
                        c->cputype = CPU_R3000;
                        __cpu_name[cpu] = "R3000";
index a6c1332..9b00362 100644 (file)
@@ -36,6 +36,11 @@ FEXPORT(ret_from_exception)
 FEXPORT(ret_from_irq)
        LONG_S  s0, TI_REGS($28)
 FEXPORT(__ret_from_irq)
+/*
+ * We can be coming here from a syscall done in the kernel space,
+ * e.g. a failed kernel_execve().
+ */
+resume_userspace_check:
        LONG_L  t0, PT_STATUS(sp)               # returning to kernel mode?
        andi    t0, t0, KU_USER
        beqz    t0, resume_kernel
@@ -162,7 +167,7 @@ work_notifysig:                             # deal with pending signals and
        move    a0, sp
        li      a1, 0
        jal     do_notify_resume        # a2 already loaded
-       j       resume_userspace
+       j       resume_userspace_check
 
 FEXPORT(syscall_exit_partial)
        local_irq_disable               # make sure need_resched doesn't
index f6ba838..86ec03f 100644 (file)
@@ -397,14 +397,14 @@ EXPORT(sysn32_call_table)
        PTR     sys_timerfd_create
        PTR     compat_sys_timerfd_gettime      /* 6285 */
        PTR     compat_sys_timerfd_settime
-       PTR     sys_signalfd4
+       PTR     compat_sys_signalfd4
        PTR     sys_eventfd2
        PTR     sys_epoll_create1
        PTR     sys_dup3                        /* 6290 */
        PTR     sys_pipe2
        PTR     sys_inotify_init1
-       PTR     sys_preadv
-       PTR     sys_pwritev
+       PTR     compat_sys_preadv
+       PTR     compat_sys_pwritev
        PTR     compat_sys_rt_tgsigqueueinfo    /* 6295 */
        PTR     sys_perf_event_open
        PTR     sys_accept4
index a53f8ec..290dc6a 100644 (file)
@@ -79,7 +79,7 @@ static struct resource data_resource = { .name = "Kernel data", };
 void __init add_memory_region(phys_t start, phys_t size, long type)
 {
        int x = boot_mem_map.nr_map;
-       struct boot_mem_map_entry *prev = boot_mem_map.map + x - 1;
+       int i;
 
        /* Sanity check */
        if (start + size < start) {
@@ -88,15 +88,29 @@ void __init add_memory_region(phys_t start, phys_t size, long type)
        }
 
        /*
-        * Try to merge with previous entry if any.  This is far less than
-        * perfect but is sufficient for most real world cases.
+        * Try to merge with existing entry, if any.
         */
-       if (x && prev->addr + prev->size == start && prev->type == type) {
-               prev->size += size;
+       for (i = 0; i < boot_mem_map.nr_map; i++) {
+               struct boot_mem_map_entry *entry = boot_mem_map.map + i;
+               unsigned long top;
+
+               if (entry->type != type)
+                       continue;
+
+               if (start + size < entry->addr)
+                       continue;                       /* no overlap */
+
+               if (entry->addr + entry->size < start)
+                       continue;                       /* no overlap */
+
+               top = max(entry->addr + entry->size, start + size);
+               entry->addr = min(entry->addr, start);
+               entry->size = top - entry->addr;
+
                return;
        }
 
-       if (x == BOOT_MEM_MAP_MAX) {
+       if (boot_mem_map.nr_map == BOOT_MEM_MAP_MAX) {
                pr_err("Ooops! Too many entries in the memory map!\n");
                return;
        }
index afc379c..06cd0c6 100644 (file)
@@ -97,7 +97,7 @@ static void cmp_init_secondary(void)
 
        /* Enable per-cpu interrupts: platform specific */
 
-       c->core = (read_c0_ebase() >> 1) & 0xff;
+       c->core = (read_c0_ebase() >> 1) & 0x1ff;
 #if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC)
        c->vpe_id = (read_c0_tcbind() >> TCBIND_CURVPE_SHIFT) & TCBIND_CURVPE;
 #endif
index 674fca4..6fa72dd 100644 (file)
@@ -1,4 +1 @@
 obj-$(CONFIG_DT_EASY50712) := easy50712.dtb.o
-
-$(obj)/%.dtb: $(obj)/%.dts
-       $(call if_changed,dtc)
index c4a82e8..eeddc58 100644 (file)
@@ -2,8 +2,9 @@
 # Makefile for MIPS-specific library files..
 #
 
-lib-y  += csum_partial.o delay.o memcpy.o memset.o \
-          strlen_user.o strncpy_user.o strnlen_user.o uncached.o
+lib-y  += bitops.o csum_partial.o delay.o memcpy.o memset.o \
+          mips-atomic.o strlen_user.o strncpy_user.o \
+          strnlen_user.o uncached.o
 
 obj-y                  += iomap.o
 obj-$(CONFIG_PCI)      += iomap-pci.o
diff --git a/arch/mips/lib/bitops.c b/arch/mips/lib/bitops.c
new file mode 100644 (file)
index 0000000..239a9c9
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * 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) 1994-1997, 99, 2000, 06, 07 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (c) 1999, 2000  Silicon Graphics, Inc.
+ */
+#include <linux/bitops.h>
+#include <linux/irqflags.h>
+#include <linux/export.h>
+
+
+/**
+ * __mips_set_bit - Atomically set a bit in memory.  This is called by
+ * set_bit() if it cannot find a faster solution.
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ */
+void __mips_set_bit(unsigned long nr, volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       *a |= mask;
+       raw_local_irq_restore(flags);
+}
+EXPORT_SYMBOL(__mips_set_bit);
+
+
+/**
+ * __mips_clear_bit - Clears a bit in memory.  This is called by clear_bit() if
+ * it cannot find a faster solution.
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ */
+void __mips_clear_bit(unsigned long nr, volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       *a &= ~mask;
+       raw_local_irq_restore(flags);
+}
+EXPORT_SYMBOL(__mips_clear_bit);
+
+
+/**
+ * __mips_change_bit - Toggle a bit in memory.  This is called by change_bit()
+ * if it cannot find a faster solution.
+ * @nr: Bit to change
+ * @addr: Address to start counting from
+ */
+void __mips_change_bit(unsigned long nr, volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       *a ^= mask;
+       raw_local_irq_restore(flags);
+}
+EXPORT_SYMBOL(__mips_change_bit);
+
+
+/**
+ * __mips_test_and_set_bit - Set a bit and return its old value.  This is
+ * called by test_and_set_bit() if it cannot find a faster solution.
+ * @nr: Bit to set
+ * @addr: Address to count from
+ */
+int __mips_test_and_set_bit(unsigned long nr,
+                           volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+       unsigned long res;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       res = (mask & *a);
+       *a |= mask;
+       raw_local_irq_restore(flags);
+       return res;
+}
+EXPORT_SYMBOL(__mips_test_and_set_bit);
+
+
+/**
+ * __mips_test_and_set_bit_lock - Set a bit and return its old value.  This is
+ * called by test_and_set_bit_lock() if it cannot find a faster solution.
+ * @nr: Bit to set
+ * @addr: Address to count from
+ */
+int __mips_test_and_set_bit_lock(unsigned long nr,
+                                volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+       unsigned long res;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       res = (mask & *a);
+       *a |= mask;
+       raw_local_irq_restore(flags);
+       return res;
+}
+EXPORT_SYMBOL(__mips_test_and_set_bit_lock);
+
+
+/**
+ * __mips_test_and_clear_bit - Clear a bit and return its old value.  This is
+ * called by test_and_clear_bit() if it cannot find a faster solution.
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ */
+int __mips_test_and_clear_bit(unsigned long nr, volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+       unsigned long res;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       res = (mask & *a);
+       *a &= ~mask;
+       raw_local_irq_restore(flags);
+       return res;
+}
+EXPORT_SYMBOL(__mips_test_and_clear_bit);
+
+
+/**
+ * __mips_test_and_change_bit - Change a bit and return its old value.  This is
+ * called by test_and_change_bit() if it cannot find a faster solution.
+ * @nr: Bit to change
+ * @addr: Address to count from
+ */
+int __mips_test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+       unsigned long res;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       res = (mask & *a);
+       *a ^= mask;
+       raw_local_irq_restore(flags);
+       return res;
+}
+EXPORT_SYMBOL(__mips_test_and_change_bit);
index 5995969..dc81ca8 100644 (file)
 #include <asm/compiler.h>
 #include <asm/war.h>
 
-inline void __delay(unsigned int loops)
+void __delay(unsigned long loops)
 {
        __asm__ __volatile__ (
        "       .set    noreorder                               \n"
        "       .align  3                                       \n"
        "1:     bnez    %0, 1b                                  \n"
+#if __SIZEOF_LONG__ == 4
        "       subu    %0, 1                                   \n"
+#else
+       "       dsubu   %0, 1                                   \n"
+#endif
        "       .set    reorder                                 \n"
        : "=r" (loops)
        : "0" (loops));
index 3f69725..a99c1d3 100644 (file)
@@ -50,8 +50,9 @@ static void dump_tlb(int first, int last)
 {
        unsigned long s_entryhi, entryhi, asid;
        unsigned long long entrylo0, entrylo1;
-       unsigned int s_index, pagemask, c0, c1, i;
+       unsigned int s_index, s_pagemask, pagemask, c0, c1, i;
 
+       s_pagemask = read_c0_pagemask();
        s_entryhi = read_c0_entryhi();
        s_index = read_c0_index();
        asid = s_entryhi & 0xff;
@@ -103,6 +104,7 @@ static void dump_tlb(int first, int last)
 
        write_c0_entryhi(s_entryhi);
        write_c0_index(s_index);
+       write_c0_pagemask(s_pagemask);
 }
 
 void dump_tlb_all(void)
diff --git a/arch/mips/lib/mips-atomic.c b/arch/mips/lib/mips-atomic.c
new file mode 100644 (file)
index 0000000..cd160be
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * 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) 1994, 95, 96, 97, 98, 99, 2003 by Ralf Baechle
+ * Copyright (C) 1996 by Paul M. Antoine
+ * Copyright (C) 1999 Silicon Graphics
+ * Copyright (C) 2000 MIPS Technologies, Inc.
+ */
+#include <asm/irqflags.h>
+#include <asm/hazards.h>
+#include <linux/compiler.h>
+#include <linux/preempt.h>
+#include <linux/export.h>
+
+#if !defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT_SMTC)
+
+/*
+ * For cli() we have to insert nops to make sure that the new value
+ * has actually arrived in the status register before the end of this
+ * macro.
+ * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs
+ * no nops at all.
+ */
+/*
+ * For TX49, operating only IE bit is not enough.
+ *
+ * If mfc0 $12 follows store and the mfc0 is last instruction of a
+ * page and fetching the next instruction causes TLB miss, the result
+ * of the mfc0 might wrongly contain EXL bit.
+ *
+ * ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008
+ *
+ * Workaround: mask EXL bit of the result or place a nop before mfc0.
+ */
+__asm__(
+       "       .macro  arch_local_irq_disable\n"
+       "       .set    push                                            \n"
+       "       .set    noat                                            \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "       mfc0    $1, $2, 1                                       \n"
+       "       ori     $1, 0x400                                       \n"
+       "       .set    noreorder                                       \n"
+       "       mtc0    $1, $2, 1                                       \n"
+#elif defined(CONFIG_CPU_MIPSR2)
+       /* see irqflags.h for inline function */
+#else
+       "       mfc0    $1,$12                                          \n"
+       "       ori     $1,0x1f                                         \n"
+       "       xori    $1,0x1f                                         \n"
+       "       .set    noreorder                                       \n"
+       "       mtc0    $1,$12                                          \n"
+#endif
+       "       irq_disable_hazard                                      \n"
+       "       .set    pop                                             \n"
+       "       .endm                                                   \n");
+
+notrace void arch_local_irq_disable(void)
+{
+       preempt_disable();
+       __asm__ __volatile__(
+               "arch_local_irq_disable"
+               : /* no outputs */
+               : /* no inputs */
+               : "memory");
+       preempt_enable();
+}
+EXPORT_SYMBOL(arch_local_irq_disable);
+
+
+__asm__(
+       "       .macro  arch_local_irq_save result                      \n"
+       "       .set    push                                            \n"
+       "       .set    reorder                                         \n"
+       "       .set    noat                                            \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "       mfc0    \\result, $2, 1                                 \n"
+       "       ori     $1, \\result, 0x400                             \n"
+       "       .set    noreorder                                       \n"
+       "       mtc0    $1, $2, 1                                       \n"
+       "       andi    \\result, \\result, 0x400                       \n"
+#elif defined(CONFIG_CPU_MIPSR2)
+       /* see irqflags.h for inline function */
+#else
+       "       mfc0    \\result, $12                                   \n"
+       "       ori     $1, \\result, 0x1f                              \n"
+       "       xori    $1, 0x1f                                        \n"
+       "       .set    noreorder                                       \n"
+       "       mtc0    $1, $12                                         \n"
+#endif
+       "       irq_disable_hazard                                      \n"
+       "       .set    pop                                             \n"
+       "       .endm                                                   \n");
+
+notrace unsigned long arch_local_irq_save(void)
+{
+       unsigned long flags;
+       preempt_disable();
+       asm volatile("arch_local_irq_save\t%0"
+                    : "=r" (flags)
+                    : /* no inputs */
+                    : "memory");
+       preempt_enable();
+       return flags;
+}
+EXPORT_SYMBOL(arch_local_irq_save);
+
+
+__asm__(
+       "       .macro  arch_local_irq_restore flags                    \n"
+       "       .set    push                                            \n"
+       "       .set    noreorder                                       \n"
+       "       .set    noat                                            \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "mfc0   $1, $2, 1                                               \n"
+       "andi   \\flags, 0x400                                          \n"
+       "ori    $1, 0x400                                               \n"
+       "xori   $1, 0x400                                               \n"
+       "or     \\flags, $1                                             \n"
+       "mtc0   \\flags, $2, 1                                          \n"
+#elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
+       /* see irqflags.h for inline function */
+#elif defined(CONFIG_CPU_MIPSR2)
+       /* see irqflags.h for inline function */
+#else
+       "       mfc0    $1, $12                                         \n"
+       "       andi    \\flags, 1                                      \n"
+       "       ori     $1, 0x1f                                        \n"
+       "       xori    $1, 0x1f                                        \n"
+       "       or      \\flags, $1                                     \n"
+       "       mtc0    \\flags, $12                                    \n"
+#endif
+       "       irq_disable_hazard                                      \n"
+       "       .set    pop                                             \n"
+       "       .endm                                                   \n");
+
+notrace void arch_local_irq_restore(unsigned long flags)
+{
+       unsigned long __tmp1;
+
+#ifdef CONFIG_MIPS_MT_SMTC
+       /*
+        * SMTC kernel needs to do a software replay of queued
+        * IPIs, at the cost of branch and call overhead on each
+        * local_irq_restore()
+        */
+       if (unlikely(!(flags & 0x0400)))
+               smtc_ipi_replay();
+#endif
+       preempt_disable();
+       __asm__ __volatile__(
+               "arch_local_irq_restore\t%0"
+               : "=r" (__tmp1)
+               : "0" (flags)
+               : "memory");
+       preempt_enable();
+}
+EXPORT_SYMBOL(arch_local_irq_restore);
+
+
+notrace void __arch_local_irq_restore(unsigned long flags)
+{
+       unsigned long __tmp1;
+
+       preempt_disable();
+       __asm__ __volatile__(
+               "arch_local_irq_restore\t%0"
+               : "=r" (__tmp1)
+               : "0" (flags)
+               : "memory");
+       preempt_enable();
+}
+EXPORT_SYMBOL(__arch_local_irq_restore);
+
+#endif /* !defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT_SMTC) */
index 87b9cfc..88e79ad 100644 (file)
@@ -120,18 +120,11 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
 
        if (cpu_context(cpu, mm) != 0) {
                unsigned long size, flags;
-               int huge = is_vm_hugetlb_page(vma);
 
                ENTER_CRITICAL(flags);
-               if (huge) {
-                       start = round_down(start, HPAGE_SIZE);
-                       end = round_up(end, HPAGE_SIZE);
-                       size = (end - start) >> HPAGE_SHIFT;
-               } else {
-                       start = round_down(start, PAGE_SIZE << 1);
-                       end = round_up(end, PAGE_SIZE << 1);
-                       size = (end - start) >> (PAGE_SHIFT + 1);
-               }
+               start = round_down(start, PAGE_SIZE << 1);
+               end = round_up(end, PAGE_SIZE << 1);
+               size = (end - start) >> (PAGE_SHIFT + 1);
                if (size <= current_cpu_data.tlbsize/2) {
                        int oldpid = read_c0_entryhi();
                        int newpid = cpu_asid(cpu, mm);
@@ -140,10 +133,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
                                int idx;
 
                                write_c0_entryhi(start | newpid);
-                               if (huge)
-                                       start += HPAGE_SIZE;
-                               else
-                                       start += (PAGE_SIZE << 1);
+                               start += (PAGE_SIZE << 1);
                                mtc0_tlbw_hazard();
                                tlb_probe();
                                tlb_probe_hazard();
@@ -320,6 +310,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
                        tlb_write_random();
                else
                        tlb_write_indexed();
+               tlbw_use_hazard();
                write_c0_pagemask(PM_DEFAULT_MASK);
        } else
 #endif
index 658a520..2833dcb 100644 (file)
@@ -148,8 +148,8 @@ enum label_id {
        label_leave,
        label_vmalloc,
        label_vmalloc_done,
-       label_tlbw_hazard,
-       label_split,
+       label_tlbw_hazard_0,
+       label_split = label_tlbw_hazard_0 + 8,
        label_tlbl_goaround1,
        label_tlbl_goaround2,
        label_nopage_tlbl,
@@ -167,7 +167,7 @@ UASM_L_LA(_second_part)
 UASM_L_LA(_leave)
 UASM_L_LA(_vmalloc)
 UASM_L_LA(_vmalloc_done)
-UASM_L_LA(_tlbw_hazard)
+/* _tlbw_hazard_x is handled differently.  */
 UASM_L_LA(_split)
 UASM_L_LA(_tlbl_goaround1)
 UASM_L_LA(_tlbl_goaround2)
@@ -181,6 +181,30 @@ UASM_L_LA(_large_segbits_fault)
 UASM_L_LA(_tlb_huge_update)
 #endif
 
+static int __cpuinitdata hazard_instance;
+
+static void uasm_bgezl_hazard(u32 **p, struct uasm_reloc **r, int instance)
+{
+       switch (instance) {
+       case 0 ... 7:
+               uasm_il_bgezl(p, r, 0, label_tlbw_hazard_0 + instance);
+               return;
+       default:
+               BUG();
+       }
+}
+
+static void uasm_bgezl_label(struct uasm_label **l, u32 **p, int instance)
+{
+       switch (instance) {
+       case 0 ... 7:
+               uasm_build_label(l, *p, label_tlbw_hazard_0 + instance);
+               break;
+       default:
+               BUG();
+       }
+}
+
 /*
  * For debug purposes.
  */
@@ -478,21 +502,28 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,
                 * This branch uses up a mtc0 hazard nop slot and saves
                 * two nops after the tlbw instruction.
                 */
-               uasm_il_bgezl(p, r, 0, label_tlbw_hazard);
+               uasm_bgezl_hazard(p, r, hazard_instance);
                tlbw(p);
-               uasm_l_tlbw_hazard(l, *p);
+               uasm_bgezl_label(l, p, hazard_instance);
+               hazard_instance++;
                uasm_i_nop(p);
                break;
 
        case CPU_R4600:
        case CPU_R4700:
-       case CPU_R5000:
-       case CPU_R5000A:
                uasm_i_nop(p);
                tlbw(p);
                uasm_i_nop(p);
                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 */
+               tlbw(p);
+               break;
+
        case CPU_R4300:
        case CPU_5KC:
        case CPU_TX49XX:
@@ -526,17 +557,6 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,
                tlbw(p);
                break;
 
-       case CPU_NEVADA:
-               uasm_i_nop(p); /* QED specifies 2 nops hazard */
-               /*
-                * This branch uses up a mtc0 hazard nop slot and saves
-                * a nop after the tlbw instruction.
-                */
-               uasm_il_bgezl(p, r, 0, label_tlbw_hazard);
-               tlbw(p);
-               uasm_l_tlbw_hazard(l, *p);
-               break;
-
        case CPU_RM7000:
                uasm_i_nop(p);
                uasm_i_nop(p);
index 80562b8..7473217 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/platform_device.h>
+#include <asm/mips-boards/maltaint.h>
 #include <mtd/mtd-abi.h>
 
 #define SMC_PORT(base, int)                                            \
@@ -48,7 +49,7 @@ static struct plat_serial8250_port uart8250_data[] = {
        SMC_PORT(0x2F8, 3),
        {
                .mapbase        = 0x1f000900,   /* The CBUS UART */
-               .irq            = MIPS_CPU_IRQ_BASE + 2,
+               .irq            = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB2,
                .uartclk        = 3686400,      /* Twice the usual clk! */
                .iotype         = UPIO_MEM32,
                .flags          = CBUS_UART_FLAGS,
index 67ae3fe..d117d46 100644 (file)
@@ -1,4 +1 @@
 obj-$(CONFIG_DT_XLP_EVP) := xlp_evp.dtb.o
-
-$(obj)/%.dtb: $(obj)/%.dts
-       $(call if_changed,dtc)
index e69de29..ae5704f 100644 (file)
@@ -0,0 +1,4 @@
+/*
+ * There isn't anything here anymore, but the file must not be empty or patch
+ * will delete it.
+ */
index 966886c..4739b83 100644 (file)
@@ -50,6 +50,6 @@ BUILTIN_DTB := y
 else
 BUILTIN_DTB := n
 endif
-core-$(BUILTIN_DTB) += arch/openrisc/boot/
+core-$(BUILTIN_DTB) += arch/openrisc/boot/dts/
 
 all: vmlinux
similarity index 75%
rename from arch/openrisc/boot/Makefile
rename to arch/openrisc/boot/dts/Makefile
index 0995835..b092d30 100644 (file)
@@ -1,5 +1,3 @@
-
-
 ifneq '$(CONFIG_OPENRISC_BUILTIN_DTB)' '""'
 BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_OPENRISC_BUILTIN_DTB)).dtb.o
 else
@@ -10,6 +8,3 @@ obj-y += $(BUILTIN_DTB)
 clean-files := *.dtb.S
 
 #DTC_FLAGS ?= -p 1024
-
-$(obj)/%.dtb: $(src)/dts/%.dts FORCE
-       $(call if_changed_dep,dtc)
index 3011029..ddedc8a 100644 (file)
@@ -84,7 +84,6 @@ asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs)
 {
        struct rt_sigframe *frame = (struct rt_sigframe __user *)regs->sp;
        sigset_t set;
-       stack_t st;
 
        /*
         * Since we stacked the signal on a dword boundary,
@@ -104,11 +103,10 @@ asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs)
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
                goto badframe;
 
-       if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
-               goto badframe;
        /* It is more difficult to avoid calling this function than to
           call it and ignore errors.  */
-       do_sigaltstack(&st, NULL, regs->sp);
+       if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)
+               goto badframe;
 
        return regs->gpr[11];
 
index 458371a..bac8deb 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 7f0f2d2..7eb616e 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 250ae35..a2db278 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 c203563..21abf4f 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 a2a57a4..9bbc0c8 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 d61de64..541639c 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
@@ -1008,5 +176,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 baebb3d..a580642 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 fd49aed..5dede04 100644 (file)
@@ -65,7 +65,8 @@ put_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
 {
        compat_sigset_t s;
 
-       if (sz != sizeof *set) panic("put_sigset32()");
+       if (sz != sizeof *set)
+               return -EINVAL;
        sigset_64to32(&s, set);
 
        return copy_to_user(up, &s, sizeof s);
@@ -77,7 +78,8 @@ get_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
        compat_sigset_t s;
        int r;
 
-       if (sz != sizeof *set) panic("put_sigset32()");
+       if (sz != sizeof *set)
+               return -EINVAL;
 
        if ((r = copy_from_user(&s, up, sz)) == 0) {
                sigset_32to64(set, &s);
index 7426e40..f76c108 100644 (file)
@@ -73,6 +73,8 @@ static unsigned long get_shared_area(struct address_space *mapping,
        struct vm_area_struct *vma;
        int offset = mapping ? get_offset(mapping) : 0;
 
+       offset = (offset + (pgoff << PAGE_SHIFT)) & 0x3FF000;
+
        addr = DCACHE_ALIGN(addr - offset) + offset;
 
        for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
index 3735abd..cbf5d59 100644 (file)
@@ -60,7 +60,7 @@
        ENTRY_SAME(fork_wrapper)
        ENTRY_SAME(read)
        ENTRY_SAME(write)
-       ENTRY_SAME(open)                /* 5 */
+       ENTRY_COMP(open)                /* 5 */
        ENTRY_SAME(close)
        ENTRY_SAME(waitpid)
        ENTRY_SAME(creat)
index 7ab286a..39ed65a 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 3444eb8..24f6680 100644 (file)
                                reg = <0>;
                        };
                };
-
-               sclpc@3c00 {
-                       compatible = "fsl,mpc5200-lpbfifo";
-                       reg = <0x3c00 0x60>;
-                       interrupts = <3 23 0>;
-               };
        };
 
        localbus {
index 9e35499..96512c0 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 38040ff..ce0ef6c 100644 (file)
@@ -42,5 +42,6 @@ static inline void svcpu_put(struct kvmppc_book3s_shadow_vcpu *svcpu)
 #define SID_SHIFT      28
 #define ESID_MASK      0xf0000000
 #define VSID_MASK      0x00fffffff0000000ULL
+#define VPN_SHIFT      12
 
 #endif /* __ASM_KVM_BOOK3S_32_H__ */
index 8734b38..8750204 100644 (file)
@@ -388,9 +388,9 @@ extern int powersave_nap;   /* set if nap mode can be used in idle loop */
 extern void power7_nap(void);
 
 #ifdef CONFIG_PSERIES_IDLE
-extern void update_smt_snooze_delay(int snooze);
+extern void update_smt_snooze_delay(int cpu, int residency);
 #else
-static inline void update_smt_snooze_delay(int snooze) {}
+static inline void update_smt_snooze_delay(int cpu, int residency) {}
 #endif
 
 extern void flush_instruction_cache(void);
index 8302af6..cf357a0 100644 (file)
@@ -50,7 +50,7 @@ static ssize_t store_smt_snooze_delay(struct device *dev,
                return -EINVAL;
 
        per_cpu(smt_snooze_delay, cpu->dev.id) = snooze;
-       update_smt_snooze_delay(snooze);
+       update_smt_snooze_delay(cpu->dev.id, snooze);
 
        return count;
 }
index 00aa612..b0f625a 100644 (file)
@@ -173,8 +173,8 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
        BUG_ON(!map);
 
        vsid = map->host_vsid;
-       vpn = (vsid << (SID_SHIFT - VPN_SHIFT)) | ((eaddr & ~ESID_MASK) >> VPN_SHIFT)
-
+       vpn = (vsid << (SID_SHIFT - VPN_SHIFT)) |
+               ((eaddr & ~ESID_MASK) >> VPN_SHIFT);
 next_pteg:
        if (rr == 16) {
                primary = !primary;
index 0db88f5..aa2465e 100644 (file)
@@ -1463,7 +1463,7 @@ static void perf_event_interrupt(struct pt_regs *regs)
                if (!event->hw.idx || is_limited_pmc(event->hw.idx))
                        continue;
                val = read_pmc(event->hw.idx);
-               if (pmc_overflow(val)) {
+               if ((int)val < 0) {
                        /* event has overflowed */
                        found = 1;
                        record_and_restart(event, val, regs);
index 8520b58..b89ef65 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 b0c3777..d588e48 100644 (file)
@@ -686,7 +686,7 @@ static int pmf_add_functions(struct pmf_device *dev, void *driverdata)
        int count = 0;
 
        for (pp = dev->node->properties; pp != 0; pp = pp->next) {
-               char *name;
+               const char *name;
                if (strncmp(pp->name, PP_PREFIX, plen) != 0)
                        continue;
                name = pp->name + plen;
index 797cd18..d16c8de 100644 (file)
@@ -449,7 +449,7 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe)
                        if (list_empty(&pe->edevs)) {
                                cnt = 0;
                                list_for_each_entry(child, &pe->child_list, child) {
-                                       if (!(pe->type & EEH_PE_INVALID)) {
+                                       if (!(child->type & EEH_PE_INVALID)) {
                                                cnt++;
                                                break;
                                        }
index d19f497..e5b0847 100644 (file)
@@ -220,7 +220,8 @@ static struct device_node *find_pe_dn(struct pci_dev *dev, int *total)
 
        /* Get the top level device in the PE */
        edev = of_node_to_eeh_dev(dn);
-       edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list);
+       if (edev->pe)
+               edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list);
        dn = eeh_dev_to_of_node(edev);
        if (!dn)
                return NULL;
index 455760b..4d806b4 100644 (file)
@@ -33,17 +33,10 @@ static int max_idle_state = MAX_IDLE_STATE_COUNT - 1;
 static struct cpuidle_device __percpu *pseries_cpuidle_devices;
 static struct cpuidle_state *cpuidle_state_table;
 
-void update_smt_snooze_delay(int snooze)
-{
-       struct cpuidle_driver *drv = cpuidle_get_driver();
-       if (drv)
-               drv->states[0].target_residency = snooze;
-}
-
 static inline void idle_loop_prolog(unsigned long *in_purr, ktime_t *kt_before)
 {
 
-       *kt_before = ktime_get_real();
+       *kt_before = ktime_get();
        *in_purr = mfspr(SPRN_PURR);
        /*
         * Indicate to the HV that we are idle. Now would be
@@ -57,7 +50,7 @@ static inline  s64 idle_loop_epilog(unsigned long in_purr, ktime_t kt_before)
        get_lppaca()->wait_state_cycles += mfspr(SPRN_PURR) - in_purr;
        get_lppaca()->idle = 0;
 
-       return ktime_to_us(ktime_sub(ktime_get_real(), kt_before));
+       return ktime_to_us(ktime_sub(ktime_get(), kt_before));
 }
 
 static int snooze_loop(struct cpuidle_device *dev,
@@ -66,32 +59,22 @@ static int snooze_loop(struct cpuidle_device *dev,
 {
        unsigned long in_purr;
        ktime_t kt_before;
-       unsigned long start_snooze;
-       long snooze = drv->states[0].target_residency;
+       int cpu = dev->cpu;
 
        idle_loop_prolog(&in_purr, &kt_before);
+       local_irq_enable();
+       set_thread_flag(TIF_POLLING_NRFLAG);
 
-       if (snooze) {
-               start_snooze = get_tb() + snooze * tb_ticks_per_usec;
-               local_irq_enable();
-               set_thread_flag(TIF_POLLING_NRFLAG);
-
-               while ((snooze < 0) || (get_tb() < start_snooze)) {
-                       if (need_resched() || cpu_is_offline(dev->cpu))
-                               goto out;
-                       ppc64_runlatch_off();
-                       HMT_low();
-                       HMT_very_low();
-               }
-
-               HMT_medium();
-               clear_thread_flag(TIF_POLLING_NRFLAG);
-               smp_mb();
-               local_irq_disable();
+       while ((!need_resched()) && cpu_online(cpu)) {
+               ppc64_runlatch_off();
+               HMT_low();
+               HMT_very_low();
        }
 
-out:
        HMT_medium();
+       clear_thread_flag(TIF_POLLING_NRFLAG);
+       smp_mb();
+
        dev->last_residency =
                (int)idle_loop_epilog(in_purr, kt_before);
        return index;
@@ -172,8 +155,8 @@ static struct cpuidle_state dedicated_states[MAX_IDLE_STATE_COUNT] = {
                .name = "CEDE",
                .desc = "CEDE",
                .flags = CPUIDLE_FLAG_TIME_VALID,
-               .exit_latency = 1,
-               .target_residency = 10,
+               .exit_latency = 10,
+               .target_residency = 100,
                .enter = &dedicated_cede_loop },
 };
 
@@ -190,6 +173,23 @@ static struct cpuidle_state shared_states[MAX_IDLE_STATE_COUNT] = {
                .enter = &shared_cede_loop },
 };
 
+void update_smt_snooze_delay(int cpu, int residency)
+{
+       struct cpuidle_driver *drv = cpuidle_get_driver();
+       struct cpuidle_device *dev = per_cpu(cpuidle_devices, cpu);
+
+       if (cpuidle_state_table != dedicated_states)
+               return;
+
+       if (residency < 0) {
+               /* Disable the Nap state on that cpu */
+               if (dev)
+                       dev->states_usage[1].disable = 1;
+       } else
+               if (drv)
+                       drv->states[1].target_residency = residency;
+}
+
 static int pseries_cpuidle_add_cpu_notifier(struct notifier_block *n,
                        unsigned long action, void *hcpu)
 {
@@ -246,10 +246,6 @@ static int pseries_cpuidle_driver_init(void)
                drv->states[drv->state_count] = /* structure copy */
                        cpuidle_state_table[idle_state];
 
-               if (cpuidle_state_table == dedicated_states)
-                       drv->states[drv->state_count].target_residency =
-                               __get_cpu_var(smt_snooze_delay);
-
                drv->state_count += 1;
        }
 
index 39f71fb..2f46681 100644 (file)
@@ -281,12 +281,11 @@ static struct property *new_property(const char *name, const int length,
        if (!new)
                return NULL;
 
-       if (!(new->name = kmalloc(strlen(name) + 1, GFP_KERNEL)))
+       if (!(new->name = kstrdup(name, GFP_KERNEL)))
                goto cleanup;
        if (!(new->value = kmalloc(length + 1, GFP_KERNEL)))
                goto cleanup;
 
-       strcpy(new->name, name);
        memcpy(new->value, value, length);
        *(((char *)new->value) + length) = 0;
        new->length = length;
index ffb93ae..01b62a6 100644 (file)
@@ -136,7 +136,7 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
        u32 pcicsrbar = 0, pcicsrbar_sz;
        u32 piwar = PIWAR_EN | PIWAR_PF | PIWAR_TGI_LOCAL |
                        PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP;
-       char *name = hose->dn->full_name;
+       const char *name = hose->dn->full_name;
        const u64 *reg;
        int len;
 
index 702256a..9193e12 100644 (file)
@@ -157,7 +157,7 @@ static int scom_debug_init_one(struct dentry *root, struct device_node *dn,
        ent->map = SCOM_MAP_INVALID;
        spin_lock_init(&ent->lock);
        snprintf(ent->name, 8, "scom%d", i);
-       ent->blob.data = dn->full_name;
+       ent->blob.data = (void*) dn->full_name;
        ent->blob.size = strlen(dn->full_name);
 
        dir = debugfs_create_dir(ent->name, root);
index 3f3d9ca..d385f39 100644 (file)
@@ -96,6 +96,7 @@ config S390
        select HAVE_MEMBLOCK_NODE_MAP
        select HAVE_CMPXCHG_LOCAL
        select HAVE_CMPXCHG_DOUBLE
+       select HAVE_ALIGNED_STRUCT_PAGE if SLUB
        select HAVE_VIRT_CPU_ACCOUNTING
        select VIRT_CPU_ACCOUNTING
        select ARCH_DISCARD_MEMBLOCK
@@ -130,6 +131,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 d80f79d..8e1fb82 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 55bde60..ad2b924 100644 (file)
@@ -9,6 +9,8 @@
 
 #define LPM_ANYPATH 0xff
 #define __MAX_CSSID 0
+#define __MAX_SUBCHANNEL 65535
+#define __MAX_SSID 3
 
 #include <asm/scsw.h>
 
index a34a9d6..18cd6b5 100644 (file)
@@ -20,7 +20,7 @@
 #define PSW32_MASK_CC          0x00003000UL
 #define PSW32_MASK_PM          0x00000f00UL
 
-#define PSW32_MASK_USER                0x00003F00UL
+#define PSW32_MASK_USER                0x0000FF00UL
 
 #define PSW32_ADDR_AMODE       0x80000000UL
 #define PSW32_ADDR_INSN                0x7FFFFFFFUL
index 7941968..5f0173a 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 dd647c9..2d3b7cb 100644 (file)
@@ -506,12 +506,15 @@ static inline int pud_bad(pud_t pud)
 
 static inline int pmd_present(pmd_t pmd)
 {
-       return (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN) != 0UL;
+       unsigned long mask = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO;
+       return (pmd_val(pmd) & mask) == _HPAGE_TYPE_NONE ||
+              !(pmd_val(pmd) & _SEGMENT_ENTRY_INV);
 }
 
 static inline int pmd_none(pmd_t pmd)
 {
-       return (pmd_val(pmd) & _SEGMENT_ENTRY_INV) != 0UL;
+       return (pmd_val(pmd) & _SEGMENT_ENTRY_INV) &&
+              !(pmd_val(pmd) & _SEGMENT_ENTRY_RO);
 }
 
 static inline int pmd_large(pmd_t pmd)
@@ -1223,6 +1226,11 @@ static inline void __pmd_idte(unsigned long address, pmd_t *pmdp)
 }
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
+
+#define SEGMENT_NONE   __pgprot(_HPAGE_TYPE_NONE)
+#define SEGMENT_RO     __pgprot(_HPAGE_TYPE_RO)
+#define SEGMENT_RW     __pgprot(_HPAGE_TYPE_RW)
+
 #define __HAVE_ARCH_PGTABLE_DEPOSIT
 extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pgtable_t pgtable);
 
@@ -1242,16 +1250,15 @@ static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
 
 static inline unsigned long massage_pgprot_pmd(pgprot_t pgprot)
 {
-       unsigned long pgprot_pmd = 0;
-
-       if (pgprot_val(pgprot) & _PAGE_INVALID) {
-               if (pgprot_val(pgprot) & _PAGE_SWT)
-                       pgprot_pmd |= _HPAGE_TYPE_NONE;
-               pgprot_pmd |= _SEGMENT_ENTRY_INV;
-       }
-       if (pgprot_val(pgprot) & _PAGE_RO)
-               pgprot_pmd |= _SEGMENT_ENTRY_RO;
-       return pgprot_pmd;
+       /*
+        * pgprot is PAGE_NONE, PAGE_RO, or PAGE_RW (see __Pxxx / __Sxxx)
+        * Convert to segment table entry format.
+        */
+       if (pgprot_val(pgprot) == pgprot_val(PAGE_NONE))
+               return pgprot_val(SEGMENT_NONE);
+       if (pgprot_val(pgprot) == pgprot_val(PAGE_RO))
+               return pgprot_val(SEGMENT_RO);
+       return pgprot_val(SEGMENT_RW);
 }
 
 static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
@@ -1269,7 +1276,9 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd)
 
 static inline pmd_t pmd_mkwrite(pmd_t pmd)
 {
-       pmd_val(pmd) &= ~_SEGMENT_ENTRY_RO;
+       /* Do not clobber _HPAGE_TYPE_NONE pages! */
+       if (!(pmd_val(pmd) & _SEGMENT_ENTRY_INV))
+               pmd_val(pmd) &= ~_SEGMENT_ENTRY_RO;
        return pmd;
 }
 
index 9ca3053..9935cbd 100644 (file)
@@ -8,6 +8,9 @@ struct cpu;
 
 #ifdef CONFIG_SCHED_BOOK
 
+extern unsigned char cpu_socket_id[NR_CPUS];
+#define topology_physical_package_id(cpu) (cpu_socket_id[cpu])
+
 extern unsigned char cpu_core_id[NR_CPUS];
 extern cpumask_t cpu_core_map[NR_CPUS];
 
index 581992d..6b4fb29 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));
 
 
index e69de29..ff1f4e7 100644 (file)
@@ -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 705588a..a5ca214 100644 (file)
@@ -239,7 +239,7 @@ typedef struct
 #define PSW_MASK_EA            0x00000000UL
 #define PSW_MASK_BA            0x00000000UL
 
-#define PSW_MASK_USER          0x00003F00UL
+#define PSW_MASK_USER          0x0000FF00UL
 
 #define PSW_ADDR_AMODE         0x80000000UL
 #define PSW_ADDR_INSN          0x7FFFFFFFUL
@@ -269,7 +269,7 @@ typedef struct
 #define PSW_MASK_EA            0x0000000100000000UL
 #define PSW_MASK_BA            0x0000000080000000UL
 
-#define PSW_MASK_USER          0x00003F8180000000UL
+#define PSW_MASK_USER          0x0000FF8180000000UL
 
 #define PSW_ADDR_AMODE         0x0000000000000000UL
 #define PSW_ADDR_INSN          0xFFFFFFFFFFFFFFFFUL
index 8df8d8a..64b2465 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 a1e8a86..593fcc9 100644 (file)
@@ -309,6 +309,10 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
        regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
                (__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 |
                (__u64)(regs32.psw.addr & PSW32_ADDR_AMODE);
+       /* Check for invalid user address space control. */
+       if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC))
+               regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) |
+                       (regs->psw.mask & ~PSW_MASK_ASC);
        regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN);
        for (i = 0; i < NUM_GPRS; i++)
                regs->gprs[i] = (__u64) regs32.gprs[i];
@@ -481,7 +485,10 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
 
        /* Set up registers for signal handler */
        regs->gprs[15] = (__force __u64) frame;
-       regs->psw.mask |= PSW_MASK_BA;          /* force amode 31 */
+       /* Force 31 bit amode and default user address space control. */
+       regs->psw.mask = PSW_MASK_BA |
+               (psw_user_bits & PSW_MASK_ASC) |
+               (regs->psw.mask & ~PSW_MASK_ASC);
        regs->psw.addr = (__force __u64) ka->sa.sa_handler;
 
        regs->gprs[2] = map_signal(sig);
@@ -549,7 +556,10 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
 
        /* Set up registers for signal handler */
        regs->gprs[15] = (__force __u64) frame;
-       regs->psw.mask |= PSW_MASK_BA;          /* force amode 31 */
+       /* Force 31 bit amode and default user address space control. */
+       regs->psw.mask = PSW_MASK_BA |
+               (psw_user_bits & PSW_MASK_ASC) |
+               (regs->psw.mask & ~PSW_MASK_ASC);
        regs->psw.addr = (__u64) ka->sa.sa_handler;
 
        regs->gprs[2] = map_signal(sig);
index ad79b84..827e094 100644 (file)
@@ -28,7 +28,7 @@ ENTRY(sys32_open_wrapper)
        llgtr   %r2,%r2                 # const char *
        lgfr    %r3,%r3                 # int
        lgfr    %r4,%r4                 # int
-       jg      sys_open                # branch to system call
+       jg      compat_sys_open         # branch to system call
 
 ENTRY(sys32_close_wrapper)
        llgfr   %r2,%r2                 # unsigned int
index acaaaf4..085a95e 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 9871b19..c4e7269 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;
        }
 
index bf05389..b6506ee 100644 (file)
@@ -44,6 +44,12 @@ _sclp_wait_int:
 #endif
        mvc     .LoldpswS1-.LbaseS1(16,%r13),0(%r8)
        mvc     0(16,%r8),0(%r9)
+#ifdef CONFIG_64BIT
+       epsw    %r6,%r7                         # set current addressing mode
+       nill    %r6,0x1                         # in new psw (31 or 64 bit mode)
+       nilh    %r7,0x8000
+       stm     %r6,%r7,0(%r8)
+#endif
        lhi     %r6,0x0200                      # cr mask for ext int (cr0.54)
        ltr     %r2,%r2
        jz      .LsetctS1
@@ -87,7 +93,7 @@ _sclp_wait_int:
        .long   0x00080000, 0x80000000+.LwaitS1 # PSW to handle ext int
 #ifdef CONFIG_64BIT
 .LextpswS1_64:
-       .quad   0x0000000180000000, .LwaitS1    # PSW to handle ext int, 64 bit
+       .quad   0, .LwaitS1                     # PSW to handle ext int, 64 bit
 #endif
 .LwaitpswS1:
        .long   0x010a0000, 0x00000000+.LloopS1 # PSW to wait for ext int
index c13a2a3..d1259d8 100644 (file)
@@ -136,6 +136,10 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
        /* Use regs->psw.mask instead of psw_user_bits to preserve PER bit. */
        regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
                (user_sregs.regs.psw.mask & PSW_MASK_USER);
+       /* Check for invalid user address space control. */
+       if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC))
+               regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) |
+                       (regs->psw.mask & ~PSW_MASK_ASC);
        /* Check for invalid amode */
        if (regs->psw.mask & PSW_MASK_EA)
                regs->psw.mask |= PSW_MASK_BA;
@@ -273,7 +277,10 @@ static int setup_frame(int sig, struct k_sigaction *ka,
 
        /* Set up registers for signal handler */
        regs->gprs[15] = (unsigned long) frame;
-       regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA;    /* 64 bit amode */
+       /* Force default amode and default user address space control. */
+       regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
+               (psw_user_bits & PSW_MASK_ASC) |
+               (regs->psw.mask & ~PSW_MASK_ASC);
        regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
 
        regs->gprs[2] = map_signal(sig);
@@ -346,7 +353,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 
        /* Set up registers for signal handler */
        regs->gprs[15] = (unsigned long) frame;
-       regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA;    /* 64 bit amode */
+       /* Force default amode and default user address space control. */
+       regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
+               (psw_user_bits & PSW_MASK_ASC) |
+               (regs->psw.mask & ~PSW_MASK_ASC);
        regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
 
        regs->gprs[2] = map_signal(sig);
index 54d93f4..dd55f7c 100644 (file)
@@ -40,6 +40,7 @@ static DEFINE_SPINLOCK(topology_lock);
 static struct mask_info core_info;
 cpumask_t cpu_core_map[NR_CPUS];
 unsigned char cpu_core_id[NR_CPUS];
+unsigned char cpu_socket_id[NR_CPUS];
 
 static struct mask_info book_info;
 cpumask_t cpu_book_map[NR_CPUS];
@@ -83,11 +84,12 @@ static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu,
                        cpumask_set_cpu(lcpu, &book->mask);
                        cpu_book_id[lcpu] = book->id;
                        cpumask_set_cpu(lcpu, &core->mask);
+                       cpu_core_id[lcpu] = rcpu;
                        if (one_core_per_cpu) {
-                               cpu_core_id[lcpu] = rcpu;
+                               cpu_socket_id[lcpu] = rcpu;
                                core = core->next;
                        } else {
-                               cpu_core_id[lcpu] = core->id;
+                               cpu_socket_id[lcpu] = core->id;
                        }
                        smp_cpu_set_polarization(lcpu, tl_cpu->pp);
                }
index de8fa9b..79cb51a 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 2d37bb8..9017a63 100644 (file)
@@ -39,7 +39,7 @@ static __always_inline unsigned long follow_table(struct mm_struct *mm,
        pmd = pmd_offset(pud, addr);
        if (pmd_none(*pmd))
                return -0x10UL;
-       if (pmd_huge(*pmd)) {
+       if (pmd_large(*pmd)) {
                if (write && (pmd_val(*pmd) & _SEGMENT_ENTRY_RO))
                        return -0x04UL;
                return (pmd_val(*pmd) & HPAGE_MASK) + (addr & ~HPAGE_MASK);
index 60acb93..1f5315d 100644 (file)
@@ -126,7 +126,7 @@ static inline int gup_pmd_range(pud_t *pudp, pud_t pud, unsigned long addr,
                 */
                if (pmd_none(pmd) || pmd_trans_splitting(pmd))
                        return 0;
-               if (unlikely(pmd_huge(pmd))) {
+               if (unlikely(pmd_large(pmd))) {
                        if (!gup_huge_pmd(pmdp, pmd, addr, next,
                                          write, pages, nr))
                                return 0;
@@ -180,8 +180,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
        addr = start;
        len = (unsigned long) nr_pages << PAGE_SHIFT;
        end = start + len;
-       if (unlikely(!access_ok(write ? VERIFY_WRITE : VERIFY_READ,
-                                       (void __user *)start, len)))
+       if ((end < start) || (end > TASK_SIZE))
                return 0;
 
        local_irq_save(flags);
@@ -229,7 +228,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
        addr = start;
        len = (unsigned long) nr_pages << PAGE_SHIFT;
        end = start + len;
-       if (end < start)
+       if ((end < start) || (end > TASK_SIZE))
                goto slow_irqon;
 
        /*
index c268bbf..02353bd 100644 (file)
@@ -148,7 +148,6 @@ score_rt_sigreturn(struct pt_regs *regs)
 {
        struct rt_sigframe __user *frame;
        sigset_t set;
-       stack_t st;
        int sig;
 
        /* Always make any pending restarted system calls return -EINTR */
@@ -168,12 +167,10 @@ score_rt_sigreturn(struct pt_regs *regs)
        else if (sig)
                force_sig(sig, current);
 
-       if (__copy_from_user(&st, &frame->rs_uc.uc_stack, sizeof(st)))
-               goto badframe;
-
        /* It is more difficult to avoid calling this function than to
           call it and ignore errors.  */
-       do_sigaltstack((stack_t __user *)&st, NULL, regs->regs[0]);
+       if (do_sigaltstack(&frame->rs_uc.uc_stack, NULL, regs->regs[0]) == -EFAULT)
+               goto badframe;
        regs->is_syscall = 0;
 
        __asm__ __volatile__(
index 86eadce..29f83be 100644 (file)
@@ -1,4 +1,3 @@
-include include/asm-generic/Kbuild.asm
 
 generic-y += bitsperlong.h
 generic-y += cputime.h
@@ -34,13 +33,3 @@ generic-y += termbits.h
 generic-y += termios.h
 generic-y += ucontext.h
 generic-y += xor.h
-
-header-y += cachectl.h
-header-y += cpu-features.h
-header-y += hw_breakpoint.h
-header-y += posix_types_32.h
-header-y += posix_types_64.h
-header-y += ptrace_32.h
-header-y += ptrace_64.h
-header-y += unistd_32.h
-header-y += unistd_64.h
index 89890f6..ec9ad59 100644 (file)
@@ -1,7 +1,8 @@
 #ifndef __ASM_SH_HW_BREAKPOINT_H
 #define __ASM_SH_HW_BREAKPOINT_H
 
-#ifdef __KERNEL__
+#include <uapi/asm/hw_breakpoint.h>
+
 #define __ARCH_HW_BREAKPOINT_H
 
 #include <linux/kdebug.h>
@@ -66,5 +67,4 @@ extern int register_sh_ubc(struct sh_ubc *);
 
 extern struct pmu perf_ops_bp;
 
-#endif /* __KERNEL__ */
 #endif /* __ASM_SH_HW_BREAKPOINT_H */
index f08449b..1aa7810 100644 (file)
@@ -1,13 +1,5 @@
-#ifdef __KERNEL__
 # ifdef CONFIG_SUPERH32
 #  include <asm/posix_types_32.h>
 # else
 #  include <asm/posix_types_64.h>
 # endif
-#else
-# ifdef __SH5__
-#  include <asm/posix_types_64.h>
-# else
-#  include <asm/posix_types_32.h>
-# endif
-#endif /* __KERNEL__ */
index a4a38df..2506c7d 100644 (file)
@@ -1,42 +1,16 @@
-#ifndef __ASM_SH_PTRACE_H
-#define __ASM_SH_PTRACE_H
-
 /*
  * Copyright (C) 1999, 2000  Niibe Yutaka
  */
+#ifndef __ASM_SH_PTRACE_H
+#define __ASM_SH_PTRACE_H
 
-#define PTRACE_GETREGS         12      /* General registers */
-#define PTRACE_SETREGS         13
-
-#define PTRACE_GETFPREGS       14      /* FPU registers */
-#define PTRACE_SETFPREGS       15
-
-#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        PTRACE_GETDSPREGS       55      /* DSP registers */
-#define        PTRACE_SETDSPREGS       56
-
-#define PT_TEXT_END_ADDR       240
-#define PT_TEXT_ADDR           244     /* &(struct user)->start_code */
-#define PT_DATA_ADDR           248     /* &(struct user)->start_data */
-#define PT_TEXT_LEN            252
-
-#if defined(__SH5__) || defined(CONFIG_CPU_SH5)
-#include <asm/ptrace_64.h>
-#else
-#include <asm/ptrace_32.h>
-#endif
-
-#ifdef __KERNEL__
 
 #include <linux/stringify.h>
 #include <linux/stddef.h>
 #include <linux/thread_info.h>
 #include <asm/addrspace.h>
 #include <asm/page.h>
+#include <uapi/asm/ptrace.h>
 
 #define user_mode(regs)                        (((regs)->sr & 0x40000000)==0)
 #define kernel_stack_pointer(_regs)    ((unsigned long)(_regs)->regs[15])
@@ -140,6 +114,4 @@ static inline unsigned long profile_pc(struct pt_regs *regs)
 #define profile_pc profile_pc
 
 #include <asm-generic/ptrace.h>
-#endif /* __KERNEL__ */
-
 #endif /* __ASM_SH_PTRACE_H */
index 2d3e906..1dd4480 100644 (file)
@@ -1,79 +1,8 @@
 #ifndef __ASM_SH_PTRACE_32_H
 #define __ASM_SH_PTRACE_32_H
 
-/*
- * GCC defines register number like this:
- * -----------------------------
- *      0 - 15 are integer registers
- *     17 - 22 are control/special registers
- *     24 - 39 fp registers
- *     40 - 47 xd registers
- *     48 -    fpscr register
- * -----------------------------
- *
- * We follows above, except:
- *     16 --- program counter (PC)
- *     22 --- syscall #
- *     23 --- floating point communication register
- */
-#define REG_REG0        0
-#define REG_REG15      15
+#include <uapi/asm/ptrace_32.h>
 
-#define REG_PC         16
-
-#define REG_PR         17
-#define REG_SR         18
-#define REG_GBR                19
-#define REG_MACH       20
-#define REG_MACL       21
-
-#define REG_SYSCALL    22
-
-#define REG_FPREG0     23
-#define REG_FPREG15    38
-#define REG_XFREG0     39
-#define REG_XFREG15    54
-
-#define REG_FPSCR      55
-#define REG_FPUL       56
-
-/*
- * This struct defines the way the registers are stored on the
- * kernel stack during a system call or other kernel entry.
- */
-struct pt_regs {
-       unsigned long regs[16];
-       unsigned long pc;
-       unsigned long pr;
-       unsigned long sr;
-       unsigned long gbr;
-       unsigned long mach;
-       unsigned long macl;
-       long tra;
-};
-
-/*
- * This struct defines the way the DSP registers are stored on the
- * kernel stack during a system call or other kernel entry.
- */
-struct pt_dspregs {
-       unsigned long   a1;
-       unsigned long   a0g;
-       unsigned long   a1g;
-       unsigned long   m0;
-       unsigned long   m1;
-       unsigned long   a0;
-       unsigned long   x0;
-       unsigned long   x1;
-       unsigned long   y0;
-       unsigned long   y1;
-       unsigned long   dsr;
-       unsigned long   rs;
-       unsigned long   re;
-       unsigned long   mod;
-};
-
-#ifdef __KERNEL__
 
 #define MAX_REG_OFFSET         offsetof(struct pt_regs, tra)
 static inline long regs_return_value(struct pt_regs *regs)
@@ -81,6 +10,4 @@ static inline long regs_return_value(struct pt_regs *regs)
        return regs->regs[0];
 }
 
-#endif /* __KERNEL__ */
-
 #endif /* __ASM_SH_PTRACE_32_H */
index eb3fcce..97f4b56 100644 (file)
@@ -1,16 +1,8 @@
 #ifndef __ASM_SH_PTRACE_64_H
 #define __ASM_SH_PTRACE_64_H
 
-struct pt_regs {
-       unsigned long long pc;
-       unsigned long long sr;
-       long long syscall_nr;
-       unsigned long long regs[63];
-       unsigned long long tregs[8];
-       unsigned long long pad[2];
-};
+#include <uapi/asm/ptrace_64.h>
 
-#ifdef __KERNEL__
 
 #define MAX_REG_OFFSET         offsetof(struct pt_regs, tregs[7])
 static inline long regs_return_value(struct pt_regs *regs)
@@ -18,6 +10,4 @@ static inline long regs_return_value(struct pt_regs *regs)
        return regs->regs[3];
 }
 
-#endif /* __KERNEL__ */
-
 #endif /* __ASM_SH_PTRACE_64_H */
index 465a22d..9923810 100644 (file)
@@ -1,9 +1,8 @@
 #ifndef _SH_SETUP_H
 #define _SH_SETUP_H
 
-#include <asm-generic/setup.h>
+#include <uapi/asm/setup.h>
 
-#ifdef __KERNEL__
 /*
  * This is set up by the setup-routine at boot-time
  */
@@ -22,6 +21,4 @@ void sh_mv_setup(void);
 void check_for_initrd(void);
 void per_cpu_trap_init(void);
 
-#endif /* __KERNEL__ */
-
 #endif /* _SH_SETUP_H */
index f8421f7..6a31053 100644 (file)
@@ -1,12 +1,11 @@
 #ifndef __ASM_SH_TYPES_H
 #define __ASM_SH_TYPES_H
 
-#include <asm-generic/types.h>
+#include <uapi/asm/types.h>
 
 /*
  * These aren't exported outside the kernel to avoid name space clashes
  */
-#ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
 #ifdef CONFIG_SUPERH32
@@ -18,6 +17,4 @@ typedef u64 reg_size_t;
 #endif
 
 #endif /* __ASSEMBLY__ */
-#endif /* __KERNEL__ */
-
 #endif /* __ASM_SH_TYPES_H */
index 307201a..38956df 100644 (file)
@@ -1,4 +1,3 @@
-#ifdef __KERNEL__
 # ifdef CONFIG_SUPERH32
 #  include <asm/unistd_32.h>
 # else
  */
 # define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
-#else
-# ifdef __SH5__
-#  include <asm/unistd_64.h>
-# else
-#  include <asm/unistd_32.h>
-# endif
-#endif
+#include <uapi/asm/unistd.h>
index baebb3d..60613ae 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 += cachectl.h
+header-y += cpu-features.h
+header-y += hw_breakpoint.h
+header-y += ioctls.h
+header-y += posix_types.h
+header-y += posix_types_32.h
+header-y += posix_types_64.h
+header-y += ptrace.h
+header-y += ptrace_32.h
+header-y += ptrace_64.h
+header-y += setup.h
+header-y += sigcontext.h
+header-y += signal.h
+header-y += sockios.h
+header-y += stat.h
+header-y += swab.h
+header-y += types.h
+header-y += unistd.h
+header-y += unistd_32.h
+header-y += unistd_64.h
diff --git a/arch/sh/include/uapi/asm/hw_breakpoint.h b/arch/sh/include/uapi/asm/hw_breakpoint.h
new file mode 100644 (file)
index 0000000..ae5704f
--- /dev/null
@@ -0,0 +1,4 @@
+/*
+ * There isn't anything here anymore, but the file must not be empty or patch
+ * will delete it.
+ */
diff --git a/arch/sh/include/uapi/asm/posix_types.h b/arch/sh/include/uapi/asm/posix_types.h
new file mode 100644 (file)
index 0000000..dc55e5a
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __KERNEL__
+# ifdef __SH5__
+#  include <asm/posix_types_64.h>
+# else
+#  include <asm/posix_types_32.h>
+# endif
+#endif /* __KERNEL__ */
diff --git a/arch/sh/include/uapi/asm/ptrace.h b/arch/sh/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..8b8c5ac
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 1999, 2000  Niibe Yutaka
+ */
+#ifndef _UAPI__ASM_SH_PTRACE_H
+#define _UAPI__ASM_SH_PTRACE_H
+
+
+#define PTRACE_GETREGS         12      /* General registers */
+#define PTRACE_SETREGS         13
+
+#define PTRACE_GETFPREGS       14      /* FPU registers */
+#define PTRACE_SETFPREGS       15
+
+#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        PTRACE_GETDSPREGS       55      /* DSP registers */
+#define        PTRACE_SETDSPREGS       56
+
+#define PT_TEXT_END_ADDR       240
+#define PT_TEXT_ADDR           244     /* &(struct user)->start_code */
+#define PT_DATA_ADDR           248     /* &(struct user)->start_data */
+#define PT_TEXT_LEN            252
+
+#if defined(__SH5__) || defined(CONFIG_CPU_SH5)
+#include <asm/ptrace_64.h>
+#else
+#include <asm/ptrace_32.h>
+#endif
+
+
+#endif /* _UAPI__ASM_SH_PTRACE_H */
diff --git a/arch/sh/include/uapi/asm/ptrace_32.h b/arch/sh/include/uapi/asm/ptrace_32.h
new file mode 100644 (file)
index 0000000..926e0ce
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef _UAPI__ASM_SH_PTRACE_32_H
+#define _UAPI__ASM_SH_PTRACE_32_H
+
+/*
+ * GCC defines register number like this:
+ * -----------------------------
+ *      0 - 15 are integer registers
+ *     17 - 22 are control/special registers
+ *     24 - 39 fp registers
+ *     40 - 47 xd registers
+ *     48 -    fpscr register
+ * -----------------------------
+ *
+ * We follows above, except:
+ *     16 --- program counter (PC)
+ *     22 --- syscall #
+ *     23 --- floating point communication register
+ */
+#define REG_REG0        0
+#define REG_REG15      15
+
+#define REG_PC         16
+
+#define REG_PR         17
+#define REG_SR         18
+#define REG_GBR                19
+#define REG_MACH       20
+#define REG_MACL       21
+
+#define REG_SYSCALL    22
+
+#define REG_FPREG0     23
+#define REG_FPREG15    38
+#define REG_XFREG0     39
+#define REG_XFREG15    54
+
+#define REG_FPSCR      55
+#define REG_FPUL       56
+
+/*
+ * This struct defines the way the registers are stored on the
+ * kernel stack during a system call or other kernel entry.
+ */
+struct pt_regs {
+       unsigned long regs[16];
+       unsigned long pc;
+       unsigned long pr;
+       unsigned long sr;
+       unsigned long gbr;
+       unsigned long mach;
+       unsigned long macl;
+       long tra;
+};
+
+/*
+ * This struct defines the way the DSP registers are stored on the
+ * kernel stack during a system call or other kernel entry.
+ */
+struct pt_dspregs {
+       unsigned long   a1;
+       unsigned long   a0g;
+       unsigned long   a1g;
+       unsigned long   m0;
+       unsigned long   m1;
+       unsigned long   a0;
+       unsigned long   x0;
+       unsigned long   x1;
+       unsigned long   y0;
+       unsigned long   y1;
+       unsigned long   dsr;
+       unsigned long   rs;
+       unsigned long   re;
+       unsigned long   mod;
+};
+
+
+#endif /* _UAPI__ASM_SH_PTRACE_32_H */
diff --git a/arch/sh/include/uapi/asm/ptrace_64.h b/arch/sh/include/uapi/asm/ptrace_64.h
new file mode 100644 (file)
index 0000000..0e52ee8
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _UAPI__ASM_SH_PTRACE_64_H
+#define _UAPI__ASM_SH_PTRACE_64_H
+
+struct pt_regs {
+       unsigned long long pc;
+       unsigned long long sr;
+       long long syscall_nr;
+       unsigned long long regs[63];
+       unsigned long long tregs[8];
+       unsigned long long pad[2];
+};
+
+
+#endif /* _UAPI__ASM_SH_PTRACE_64_H */
diff --git a/arch/sh/include/uapi/asm/setup.h b/arch/sh/include/uapi/asm/setup.h
new file mode 100644 (file)
index 0000000..552df83
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/setup.h>
diff --git a/arch/sh/include/uapi/asm/types.h b/arch/sh/include/uapi/asm/types.h
new file mode 100644 (file)
index 0000000..b9e79bc
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/types.h>
diff --git a/arch/sh/include/uapi/asm/unistd.h b/arch/sh/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..eeef88d
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __KERNEL__
+# ifdef __SH5__
+#  include <asm/unistd_64.h>
+# else
+#  include <asm/unistd_32.h>
+# endif
+#endif
similarity index 99%
rename from arch/sh/include/asm/unistd_32.h
rename to arch/sh/include/uapi/asm/unistd_32.h
index 72fd1e0..9e465f2 100644 (file)
 #define __NR_setns             364
 #define __NR_process_vm_readv  365
 #define __NR_process_vm_writev 366
+#define __NR_kcmp              367
 
-#define NR_syscalls 367
+#define NR_syscalls 368
 
 #endif /* __ASM_SH_UNISTD_32_H */
similarity index 99%
rename from arch/sh/include/asm/unistd_64.h
rename to arch/sh/include/uapi/asm/unistd_64.h
index a28edc3..8e3a2ed 100644 (file)
 #define __NR_setns             375
 #define __NR_process_vm_readv  376
 #define __NR_process_vm_writev 377
+#define __NR_kcmp              378
 
-#define NR_syscalls 378
+#define NR_syscalls 379
 
 #endif /* __ASM_SH_UNISTD_64_H */
index 2385381..d867cd9 100644 (file)
@@ -347,7 +347,6 @@ asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3,
 {
        struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (long) REF_REG_SP;
        sigset_t set;
-       stack_t __user st;
        long long ret;
 
        /* Always make any pending restarted system calls return -EINTR */
@@ -365,11 +364,10 @@ asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3,
                goto badframe;
        regs->pc -= 4;
 
-       if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
-               goto badframe;
        /* It is more difficult to avoid calling this function than to
           call it and ignore errors.  */
-       do_sigaltstack(&st, NULL, REF_REG_SP);
+       if (do_sigaltstack(&frame->uc.uc_stack, NULL, REF_REG_SP) == -EFAULT)
+               goto badframe;
 
        return (int) ret;
 
index 4b68f0f..fe97ae5 100644 (file)
@@ -384,3 +384,4 @@ ENTRY(sys_call_table)
        .long sys_setns
        .long sys_process_vm_readv      /* 365 */
        .long sys_process_vm_writev
+       .long sys_kcmp
index 0956345..5c7b1c6 100644 (file)
@@ -404,3 +404,4 @@ sys_call_table:
        .long sys_setns                 /* 375 */
        .long sys_process_vm_readv
        .long sys_process_vm_writev
+       .long sys_kcmp
index b6b442b..9f2edb5 100644 (file)
@@ -20,6 +20,7 @@ config SPARC
        select HAVE_ARCH_TRACEHOOK
        select SYSCTL_EXCEPTION_TRACE
        select ARCH_WANT_OPTIONAL_GPIOLIB
+       select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
        select RTC_CLASS
        select RTC_DRV_M48T59
        select HAVE_IRQ_WORK
index c0a798f..bb7c951 100644 (file)
@@ -81,18 +81,18 @@ static void usage(void)
 
 static int start_line(const char *line)
 {
-       if (strcmp(line + 8, " T _start\n") == 0)
+       if (strcmp(line + 10, " _start\n") == 0)
                return 1;
-       else if (strcmp(line + 16, " T _start\n") == 0)
+       else if (strcmp(line + 18, " _start\n") == 0)
                return 1;
        return 0;
 }
 
 static int end_line(const char *line)
 {
-       if (strcmp(line + 8, " A _end\n") == 0)
+       if (strcmp(line + 10, " _end\n") == 0)
                return 1;
-       else if (strcmp (line + 16, " A _end\n") == 0)
+       else if (strcmp (line + 18, " _end\n") == 0)
                return 1;
        return 0;
 }
@@ -100,8 +100,8 @@ static int end_line(const char *line)
 /*
  * Find address for start and end in System.map.
  * The file looks like this:
- * f0004000 T _start
- * f0379f79 A _end
+ * f0004000 ... _start
+ * f0379f79 ... _end
  * 1234567890123456
  * ^coloumn 1
  * There is support for 64 bit addresses too.
index 6ae1ad5..5d469d8 100644 (file)
@@ -13,13 +13,13 @@ obj-$(CONFIG_CRYPTO_DES_SPARC64) += camellia-sparc64.o
 
 obj-$(CONFIG_CRYPTO_CRC32C_SPARC64) += crc32c-sparc64.o
 
-sha1-sparc64-y := sha1_asm.o sha1_glue.o crop_devid.o
-sha256-sparc64-y := sha256_asm.o sha256_glue.o crop_devid.o
-sha512-sparc64-y := sha512_asm.o sha512_glue.o crop_devid.o
-md5-sparc64-y := md5_asm.o md5_glue.o crop_devid.o
+sha1-sparc64-y := sha1_asm.o sha1_glue.o
+sha256-sparc64-y := sha256_asm.o sha256_glue.o
+sha512-sparc64-y := sha512_asm.o sha512_glue.o
+md5-sparc64-y := md5_asm.o md5_glue.o
 
-aes-sparc64-y := aes_asm.o aes_glue.o crop_devid.o
-des-sparc64-y := des_asm.o des_glue.o crop_devid.o
-camellia-sparc64-y := camellia_asm.o camellia_glue.o crop_devid.o
+aes-sparc64-y := aes_asm.o aes_glue.o
+des-sparc64-y := des_asm.o des_glue.o
+camellia-sparc64-y := camellia_asm.o camellia_glue.o
 
-crc32c-sparc64-y := crc32c_asm.o crc32c_glue.o crop_devid.o
+crc32c-sparc64-y := crc32c_asm.o crc32c_glue.o
index 8f1c998..3965d1d 100644 (file)
@@ -475,3 +475,5 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("AES Secure Hash Algorithm, sparc64 aes opcode accelerated");
 
 MODULE_ALIAS("aes");
+
+#include "crop_devid.c"
index 42905c0..62c89af 100644 (file)
@@ -320,3 +320,5 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Camellia Cipher Algorithm, sparc64 camellia opcode accelerated");
 
 MODULE_ALIAS("aes");
+
+#include "crop_devid.c"
index 0bd89ce..5162fad 100644 (file)
@@ -177,3 +177,5 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("CRC32c (Castagnoli), sparc64 crc32c opcode accelerated");
 
 MODULE_ALIAS("crc32c");
+
+#include "crop_devid.c"
index c4940c2..41524ce 100644 (file)
@@ -527,3 +527,5 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms, sparc64 des opcode accelerated");
 
 MODULE_ALIAS("des");
+
+#include "crop_devid.c"
index 603d723..09a9ea1 100644 (file)
@@ -186,3 +186,5 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("MD5 Secure Hash Algorithm, sparc64 md5 opcode accelerated");
 
 MODULE_ALIAS("md5");
+
+#include "crop_devid.c"
index 2bbb20b..6cd5f29 100644 (file)
@@ -181,3 +181,5 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, sparc64 sha1 opcode accelerated");
 
 MODULE_ALIAS("sha1");
+
+#include "crop_devid.c"
index 591e656..04f555a 100644 (file)
@@ -239,3 +239,5 @@ MODULE_DESCRIPTION("SHA-224 and SHA-256 Secure Hash Algorithm, sparc64 sha256 op
 
 MODULE_ALIAS("sha224");
 MODULE_ALIAS("sha256");
+
+#include "crop_devid.c"
index 486f0a2..f04d199 100644 (file)
@@ -224,3 +224,5 @@ MODULE_DESCRIPTION("SHA-384 and SHA-512 Secure Hash Algorithm, sparc64 sha512 op
 
 MODULE_ALIAS("sha384");
 MODULE_ALIAS("sha512");
+
+#include "crop_devid.c"
index ce35a1c..be56a24 100644 (file)
@@ -1,7 +1,7 @@
 /* atomic.h: Thankfully the V9 is at least reasonable for this
  *           stuff.
  *
- * Copyright (C) 1996, 1997, 2000 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1996, 1997, 2000, 2012 David S. Miller (davem@redhat.com)
  */
 
 #ifndef __ARCH_SPARC64_ATOMIC__
@@ -106,6 +106,8 @@ static inline long atomic64_add_unless(atomic64_t *v, long a, long u)
 
 #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
 
+extern long atomic64_dec_if_positive(atomic64_t *v);
+
 /* Atomic operations are already serializing */
 #define smp_mb__before_atomic_dec()    barrier()
 #define smp_mb__after_atomic_dec()     barrier()
index db3af0d..4e02086 100644 (file)
@@ -1,6 +1,46 @@
 #ifndef _SPARC64_BACKOFF_H
 #define _SPARC64_BACKOFF_H
 
+/* The macros in this file implement an exponential backoff facility
+ * for atomic operations.
+ *
+ * When multiple threads compete on an atomic operation, it is
+ * possible for one thread to be continually denied a successful
+ * completion of the compare-and-swap instruction.  Heavily
+ * threaded cpu implementations like Niagara can compound this
+ * problem even further.
+ *
+ * When an atomic operation fails and needs to be retried, we spin a
+ * certain number of times.  At each subsequent failure of the same
+ * operation we double the spin count, realizing an exponential
+ * backoff.
+ *
+ * When we spin, we try to use an operation that will cause the
+ * current cpu strand to block, and therefore make the core fully
+ * available to any other other runnable strands.  There are two
+ * options, based upon cpu capabilities.
+ *
+ * On all cpus prior to SPARC-T4 we do three dummy reads of the
+ * condition code register.  Each read blocks the strand for something
+ * between 40 and 50 cpu cycles.
+ *
+ * For SPARC-T4 and later we have a special "pause" instruction
+ * available.  This is implemented using writes to register %asr27.
+ * The cpu will block the number of cycles written into the register,
+ * unless a disrupting trap happens first.  SPARC-T4 specifically
+ * implements pause with a granularity of 8 cycles.  Each strand has
+ * an internal pause counter which decrements every 8 cycles.  So the
+ * chip shifts the %asr27 value down by 3 bits, and writes the result
+ * into the pause counter.  If a value smaller than 8 is written, the
+ * chip blocks for 1 cycle.
+ *
+ * To achieve the same amount of backoff as the three %ccr reads give
+ * on earlier chips, we shift the backoff value up by 7 bits.  (Three
+ * %ccr reads block for about 128 cycles, 1 << 7 == 128) We write the
+ * whole amount we want to block into the pause register, rather than
+ * loop writing 128 each time.
+ */
+
 #define BACKOFF_LIMIT  (4 * 1024)
 
 #ifdef CONFIG_SMP
 #define BACKOFF_LABEL(spin_label, continue_label) \
        spin_label
 
-#define BACKOFF_SPIN(reg, tmp, label)  \
-       mov     reg, tmp; \
-88:    brnz,pt tmp, 88b; \
-        sub    tmp, 1, tmp; \
-       set     BACKOFF_LIMIT, tmp; \
-       cmp     reg, tmp; \
-       bg,pn   %xcc, label; \
-        nop; \
-       ba,pt   %xcc, label; \
-        sllx   reg, 1, reg;
+#define BACKOFF_SPIN(reg, tmp, label)          \
+       mov             reg, tmp;               \
+88:    rd              %ccr, %g0;              \
+       rd              %ccr, %g0;              \
+       rd              %ccr, %g0;              \
+       .section        .pause_3insn_patch,"ax";\
+       .word           88b;                    \
+       sllx            tmp, 7, tmp;            \
+       wr              tmp, 0, %asr27;         \
+       clr             tmp;                    \
+       .previous;                              \
+       brnz,pt         tmp, 88b;               \
+        sub            tmp, 1, tmp;            \
+       set             BACKOFF_LIMIT, tmp;     \
+       cmp             reg, tmp;               \
+       bg,pn           %xcc, label;            \
+        nop;                                   \
+       ba,pt           %xcc, label;            \
+        sllx           reg, 1, reg;
 
 #else
 
index cef99fb..830502f 100644 (file)
@@ -232,9 +232,10 @@ static inline void __user *arch_compat_alloc_user_space(long len)
        struct pt_regs *regs = current_thread_info()->kregs;
        unsigned long usp = regs->u_regs[UREG_I6];
 
-       if (!(test_thread_flag(TIF_32BIT)))
+       if (test_thread_64bit_stack(usp))
                usp += STACK_BIAS;
-       else
+
+       if (test_thread_flag(TIF_32BIT))
                usp &= 0xffffffffUL;
 
        usp -= len;
index 4e5a483..721e25f 100644 (file)
@@ -196,7 +196,22 @@ extern unsigned long get_wchan(struct task_struct *task);
 #define KSTK_EIP(tsk)  (task_pt_regs(tsk)->tpc)
 #define KSTK_ESP(tsk)  (task_pt_regs(tsk)->u_regs[UREG_FP])
 
-#define cpu_relax()    barrier()
+/* Please see the commentary in asm/backoff.h for a description of
+ * what these instructions are doing and how they have been choosen.
+ * To make a long story short, we are trying to yield the current cpu
+ * strand during busy loops.
+ */
+#define cpu_relax()    asm volatile("\n99:\n\t"                        \
+                                    "rd        %%ccr, %%g0\n\t"        \
+                                    "rd        %%ccr, %%g0\n\t"        \
+                                    "rd        %%ccr, %%g0\n\t"        \
+                                    ".section  .pause_3insn_patch,\"ax\"\n\t"\
+                                    ".word     99b\n\t"                \
+                                    "wr        %%g0, 128, %%asr27\n\t" \
+                                    "nop\n\t"                          \
+                                    "nop\n\t"                          \
+                                    ".previous"                        \
+                                    ::: "memory")
 
 /* Prefetch support.  This is tuned for UltraSPARC-III and later.
  * UltraSPARC-I will treat these as nops, and UltraSPARC-II has
index c287651..67c6257 100644 (file)
@@ -63,5 +63,13 @@ extern char *of_console_options;
 extern void irq_trans_init(struct device_node *dp);
 extern char *build_path_component(struct device_node *dp);
 
+/* SPARC has local implementations */
+extern int of_address_to_resource(struct device_node *dev, int index,
+                                 struct resource *r);
+#define of_address_to_resource of_address_to_resource
+
+void __iomem *of_iomap(struct device_node *node, int index);
+#define of_iomap of_iomap
+
 #endif /* __KERNEL__ */
 #endif /* _SPARC_PROM_H */
index 0c6f6b0..da43bdc 100644 (file)
@@ -42,7 +42,18 @@ struct global_reg_snapshot {
        struct thread_info      *thread;
        unsigned long           pad1;
 };
-extern struct global_reg_snapshot global_reg_snapshot[NR_CPUS];
+
+struct global_pmu_snapshot {
+       unsigned long           pcr[4];
+       unsigned long           pic[4];
+};
+
+union global_cpu_snapshot {
+       struct global_reg_snapshot      reg;
+       struct global_pmu_snapshot      pmu;
+};
+
+extern union global_cpu_snapshot global_cpu_snapshot[NR_CPUS];
 
 #define force_successful_syscall_return()          \
 do {   current_thread_info()->syscall_noerror = 1; \
index 29862a9..dd3bef4 100644 (file)
@@ -48,6 +48,7 @@ extern void smp_fill_in_sib_core_maps(void);
 extern void cpu_play_dead(void);
 
 extern void smp_fetch_global_regs(void);
+extern void smp_fetch_global_pmu(void);
 
 struct seq_file;
 void smp_bogo(struct seq_file *);
@@ -65,6 +66,7 @@ extern void __cpu_die(unsigned int cpu);
 #define hard_smp_processor_id()                0
 #define smp_fill_in_sib_core_maps() do { } while (0)
 #define smp_fetch_global_regs() do { } while (0)
+#define smp_fetch_global_pmu() do { } while (0)
 
 #endif /* !(CONFIG_SMP) */
 
index 4e22766..a3fe4dc 100644 (file)
@@ -259,6 +259,11 @@ static inline bool test_and_clear_restore_sigmask(void)
 
 #define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
 
+#define thread32_stack_is_64bit(__SP) (((__SP) & 0x1) != 0)
+#define test_thread_64bit_stack(__SP) \
+       ((test_thread_flag(TIF_32BIT) && !thread32_stack_is_64bit(__SP)) ? \
+        false : true)
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
index 48f2807..71b5a67 100644 (file)
@@ -372,7 +372,9 @@ etrap_spill_fixup_64bit:                            \
 
 /* Normal 32bit spill */
 #define SPILL_2_GENERIC(ASI)                           \
-       srl     %sp, 0, %sp;                            \
+       and     %sp, 1, %g3;                            \
+       brnz,pn %g3, (. - (128 + 4));                   \
+        srl    %sp, 0, %sp;                            \
        stwa    %l0, [%sp + %g0] ASI;                   \
        mov     0x04, %g3;                              \
        stwa    %l1, [%sp + %g3] ASI;                   \
@@ -398,14 +400,16 @@ etrap_spill_fixup_64bit:                          \
        stwa    %i6, [%g1 + %g0] ASI;                   \
        stwa    %i7, [%g1 + %g3] ASI;                   \
        saved;                                          \
-        retry; nop; nop;                               \
+        retry;                                         \
        b,a,pt  %xcc, spill_fixup_dax;                  \
        b,a,pt  %xcc, spill_fixup_mna;                  \
        b,a,pt  %xcc, spill_fixup;
 
 #define SPILL_2_GENERIC_ETRAP          \
 etrap_user_spill_32bit:                        \
-       srl     %sp, 0, %sp;            \
+       and     %sp, 1, %g3;            \
+       brnz,pn %g3, etrap_user_spill_64bit;    \
+        srl    %sp, 0, %sp;            \
        stwa    %l0, [%sp + 0x00] %asi; \
        stwa    %l1, [%sp + 0x04] %asi; \
        stwa    %l2, [%sp + 0x08] %asi; \
@@ -427,7 +431,7 @@ etrap_user_spill_32bit:                     \
        ba,pt   %xcc, etrap_save;       \
         wrpr   %g1, %cwp;              \
        nop; nop; nop; nop;             \
-       nop; nop; nop; nop;             \
+       nop; nop;                       \
        ba,a,pt %xcc, etrap_spill_fixup_32bit; \
        ba,a,pt %xcc, etrap_spill_fixup_32bit; \
        ba,a,pt %xcc, etrap_spill_fixup_32bit;
@@ -592,7 +596,9 @@ user_rtt_fill_64bit:                                        \
 
 /* Normal 32bit fill */
 #define FILL_2_GENERIC(ASI)                            \
-       srl     %sp, 0, %sp;                            \
+       and     %sp, 1, %g3;                            \
+       brnz,pn %g3, (. - (128 + 4));                   \
+        srl    %sp, 0, %sp;                            \
        lduwa   [%sp + %g0] ASI, %l0;                   \
        mov     0x04, %g2;                              \
        mov     0x08, %g3;                              \
@@ -616,14 +622,16 @@ user_rtt_fill_64bit:                                      \
        lduwa   [%g1 + %g3] ASI, %i6;                   \
        lduwa   [%g1 + %g5] ASI, %i7;                   \
        restored;                                       \
-       retry; nop; nop; nop; nop;                      \
+       retry; nop; nop;                                \
        b,a,pt  %xcc, fill_fixup_dax;                   \
        b,a,pt  %xcc, fill_fixup_mna;                   \
        b,a,pt  %xcc, fill_fixup;
 
 #define FILL_2_GENERIC_RTRAP                           \
 user_rtt_fill_32bit:                                   \
-       srl     %sp, 0, %sp;                            \
+       and     %sp, 1, %g3;                            \
+       brnz,pn %g3, user_rtt_fill_64bit;               \
+        srl    %sp, 0, %sp;                            \
        lduwa   [%sp + 0x00] %asi, %l0;                 \
        lduwa   [%sp + 0x04] %asi, %l1;                 \
        lduwa   [%sp + 0x08] %asi, %l2;                 \
@@ -643,7 +651,7 @@ user_rtt_fill_32bit:                                        \
        ba,pt   %xcc, user_rtt_pre_restore;             \
         restored;                                      \
        nop; nop; nop; nop; nop;                        \
-       nop; nop; nop; nop; nop;                        \
+       nop; nop; nop;                                  \
        ba,a,pt %xcc, user_rtt_fill_fixup;              \
        ba,a,pt %xcc, user_rtt_fill_fixup;              \
        ba,a,pt %xcc, user_rtt_fill_fixup;
index e69de29..ae5704f 100644 (file)
@@ -0,0 +1,4 @@
+/*
+ * There isn't anything here anymore, but the file must not be empty or patch
+ * will delete it.
+ */
index 8974ef7..cac719d 100644 (file)
 #define __NR_setns             337
 #define __NR_process_vm_readv  338
 #define __NR_process_vm_writev 339
+#define __NR_kern_features     340
+#define __NR_kcmp              341
 
-#define NR_syscalls            340
+#define NR_syscalls            342
+
+/* Bitmask values returned from kern_features system call.  */
+#define KERN_FEATURE_MIXED_MODE_STACK  0x00000001
 
 #ifdef __32bit_syscall_numbers__
 /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
index 0c218e4..cc3c5cb 100644 (file)
@@ -59,6 +59,13 @@ struct popc_6insn_patch_entry {
 extern struct popc_6insn_patch_entry __popc_6insn_patch,
        __popc_6insn_patch_end;
 
+struct pause_patch_entry {
+       unsigned int    addr;
+       unsigned int    insns[3];
+};
+extern struct pause_patch_entry __pause_3insn_patch,
+       __pause_3insn_patch_end;
+
 extern void __init per_cpu_patch(void);
 extern void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *,
                                    struct sun4v_1insn_patch_entry *);
index f8b6eee..87f60ee 100644 (file)
@@ -56,11 +56,13 @@ static inline unsigned int leon_eirq_get(int cpu)
 static void leon_handle_ext_irq(unsigned int irq, struct irq_desc *desc)
 {
        unsigned int eirq;
+       struct irq_bucket *p;
        int cpu = sparc_leon3_cpuid();
 
        eirq = leon_eirq_get(cpu);
-       if ((eirq & 0x10) && irq_map[eirq]->irq) /* bit4 tells if IRQ happened */
-               generic_handle_irq(irq_map[eirq]->irq);
+       p = irq_map[eirq];
+       if ((eirq & 0x10) && p && p->irq) /* bit4 tells if IRQ happened */
+               generic_handle_irq(p->irq);
 }
 
 /* The extended IRQ controller has been found, this function registers it */
index 918a203..5f68853 100644 (file)
@@ -88,7 +88,7 @@ struct pci_pbm_info {
        int                             chip_revision;
 
        /* Name used for top-level resources. */
-       char                            *name;
+       const char                      *name;
 
        /* OBP specific information. */
        struct platform_device          *op;
index e48651d..b5c38fa 100644 (file)
@@ -817,15 +817,17 @@ static u64 nop_for_index(int idx)
 
 static inline void sparc_pmu_enable_event(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc, int idx)
 {
-       u64 val, mask = mask_for_index(idx);
+       u64 enc, val, mask = mask_for_index(idx);
        int pcr_index = 0;
 
        if (sparc_pmu->num_pcrs > 1)
                pcr_index = idx;
 
+       enc = perf_event_get_enc(cpuc->events[idx]);
+
        val = cpuc->pcr[pcr_index];
        val &= ~mask;
-       val |= hwc->config;
+       val |= event_encoding(enc, idx);
        cpuc->pcr[pcr_index] = val;
 
        pcr_ops->write_pcr(pcr_index, cpuc->pcr[pcr_index]);
@@ -1738,8 +1740,6 @@ static void perf_callchain_user_64(struct perf_callchain_entry *entry,
 {
        unsigned long ufp;
 
-       perf_callchain_store(entry, regs->tpc);
-
        ufp = regs->u_regs[UREG_I6] + STACK_BIAS;
        do {
                struct sparc_stackf *usf, sf;
@@ -1760,19 +1760,27 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry,
 {
        unsigned long ufp;
 
-       perf_callchain_store(entry, regs->tpc);
-
        ufp = regs->u_regs[UREG_I6] & 0xffffffffUL;
        do {
-               struct sparc_stackf32 *usf, sf;
                unsigned long pc;
 
-               usf = (struct sparc_stackf32 *) ufp;
-               if (__copy_from_user_inatomic(&sf, usf, sizeof(sf)))
-                       break;
+               if (thread32_stack_is_64bit(ufp)) {
+                       struct sparc_stackf *usf, sf;
 
-               pc = sf.callers_pc;
-               ufp = (unsigned long)sf.fp;
+                       ufp += STACK_BIAS;
+                       usf = (struct sparc_stackf *) ufp;
+                       if (__copy_from_user_inatomic(&sf, usf, sizeof(sf)))
+                               break;
+                       pc = sf.callers_pc & 0xffffffff;
+                       ufp = ((unsigned long) sf.fp) & 0xffffffff;
+               } else {
+                       struct sparc_stackf32 *usf, sf;
+                       usf = (struct sparc_stackf32 *) ufp;
+                       if (__copy_from_user_inatomic(&sf, usf, sizeof(sf)))
+                               break;
+                       pc = sf.callers_pc;
+                       ufp = (unsigned long)sf.fp;
+               }
                perf_callchain_store(entry, pc);
        } while (entry->nr < PERF_MAX_STACK_DEPTH);
 }
@@ -1780,6 +1788,11 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry,
 void
 perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
+       perf_callchain_store(entry, regs->tpc);
+
+       if (!current->mm)
+               return;
+
        flushw_user();
        if (test_thread_flag(TIF_32BIT))
                perf_callchain_user_32(entry, regs);
index fcaa594..c6e0c29 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/tick.h>
 #include <linux/init.h>
 #include <linux/cpu.h>
+#include <linux/perf_event.h>
 #include <linux/elfcore.h>
 #include <linux/sysrq.h>
 #include <linux/nmi.h>
@@ -47,6 +48,7 @@
 #include <asm/syscalls.h>
 #include <asm/irq_regs.h>
 #include <asm/smp.h>
+#include <asm/pcr.h>
 
 #include "kstack.h"
 
@@ -204,18 +206,22 @@ void show_regs(struct pt_regs *regs)
        show_stack(current, (unsigned long *) regs->u_regs[UREG_FP]);
 }
 
-struct global_reg_snapshot global_reg_snapshot[NR_CPUS];
-static DEFINE_SPINLOCK(global_reg_snapshot_lock);
+union global_cpu_snapshot global_cpu_snapshot[NR_CPUS];
+static DEFINE_SPINLOCK(global_cpu_snapshot_lock);
 
 static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs,
                              int this_cpu)
 {
+       struct global_reg_snapshot *rp;
+
        flushw_all();
 
-       global_reg_snapshot[this_cpu].tstate = regs->tstate;
-       global_reg_snapshot[this_cpu].tpc = regs->tpc;
-       global_reg_snapshot[this_cpu].tnpc = regs->tnpc;
-       global_reg_snapshot[this_cpu].o7 = regs->u_regs[UREG_I7];
+       rp = &global_cpu_snapshot[this_cpu].reg;
+
+       rp->tstate = regs->tstate;
+       rp->tpc = regs->tpc;
+       rp->tnpc = regs->tnpc;
+       rp->o7 = regs->u_regs[UREG_I7];
 
        if (regs->tstate & TSTATE_PRIV) {
                struct reg_window *rw;
@@ -223,17 +229,17 @@ static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs,
                rw = (struct reg_window *)
                        (regs->u_regs[UREG_FP] + STACK_BIAS);
                if (kstack_valid(tp, (unsigned long) rw)) {
-                       global_reg_snapshot[this_cpu].i7 = rw->ins[7];
+                       rp->i7 = rw->ins[7];
                        rw = (struct reg_window *)
                                (rw->ins[6] + STACK_BIAS);
                        if (kstack_valid(tp, (unsigned long) rw))
-                               global_reg_snapshot[this_cpu].rpc = rw->ins[7];
+                               rp->rpc = rw->ins[7];
                }
        } else {
-               global_reg_snapshot[this_cpu].i7 = 0;
-               global_reg_snapshot[this_cpu].rpc = 0;
+               rp->i7 = 0;
+               rp->rpc = 0;
        }
-       global_reg_snapshot[this_cpu].thread = tp;
+       rp->thread = tp;
 }
 
 /* In order to avoid hangs we do not try to synchronize with the
@@ -261,9 +267,9 @@ void arch_trigger_all_cpu_backtrace(void)
        if (!regs)
                regs = tp->kregs;
 
-       spin_lock_irqsave(&global_reg_snapshot_lock, flags);
+       spin_lock_irqsave(&global_cpu_snapshot_lock, flags);
 
-       memset(global_reg_snapshot, 0, sizeof(global_reg_snapshot));
+       memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot));
 
        this_cpu = raw_smp_processor_id();
 
@@ -272,7 +278,7 @@ void arch_trigger_all_cpu_backtrace(void)
        smp_fetch_global_regs();
 
        for_each_online_cpu(cpu) {
-               struct global_reg_snapshot *gp = &global_reg_snapshot[cpu];
+               struct global_reg_snapshot *gp = &global_cpu_snapshot[cpu].reg;
 
                __global_reg_poll(gp);
 
@@ -295,9 +301,9 @@ void arch_trigger_all_cpu_backtrace(void)
                }
        }
 
-       memset(global_reg_snapshot, 0, sizeof(global_reg_snapshot));
+       memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot));
 
-       spin_unlock_irqrestore(&global_reg_snapshot_lock, flags);
+       spin_unlock_irqrestore(&global_cpu_snapshot_lock, flags);
 }
 
 #ifdef CONFIG_MAGIC_SYSRQ
@@ -309,16 +315,90 @@ static void sysrq_handle_globreg(int key)
 
 static struct sysrq_key_op sparc_globalreg_op = {
        .handler        = sysrq_handle_globreg,
-       .help_msg       = "Globalregs",
+       .help_msg       = "global-regs(Y)",
        .action_msg     = "Show Global CPU Regs",
 };
 
-static int __init sparc_globreg_init(void)
+static void __global_pmu_self(int this_cpu)
 {
-       return register_sysrq_key('y', &sparc_globalreg_op);
+       struct global_pmu_snapshot *pp;
+       int i, num;
+
+       pp = &global_cpu_snapshot[this_cpu].pmu;
+
+       num = 1;
+       if (tlb_type == hypervisor &&
+           sun4v_chip_type >= SUN4V_CHIP_NIAGARA4)
+               num = 4;
+
+       for (i = 0; i < num; i++) {
+               pp->pcr[i] = pcr_ops->read_pcr(i);
+               pp->pic[i] = pcr_ops->read_pic(i);
+       }
 }
 
-core_initcall(sparc_globreg_init);
+static void __global_pmu_poll(struct global_pmu_snapshot *pp)
+{
+       int limit = 0;
+
+       while (!pp->pcr[0] && ++limit < 100) {
+               barrier();
+               udelay(1);
+       }
+}
+
+static void pmu_snapshot_all_cpus(void)
+{
+       unsigned long flags;
+       int this_cpu, cpu;
+
+       spin_lock_irqsave(&global_cpu_snapshot_lock, flags);
+
+       memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot));
+
+       this_cpu = raw_smp_processor_id();
+
+       __global_pmu_self(this_cpu);
+
+       smp_fetch_global_pmu();
+
+       for_each_online_cpu(cpu) {
+               struct global_pmu_snapshot *pp = &global_cpu_snapshot[cpu].pmu;
+
+               __global_pmu_poll(pp);
+
+               printk("%c CPU[%3d]: PCR[%08lx:%08lx:%08lx:%08lx] PIC[%08lx:%08lx:%08lx:%08lx]\n",
+                      (cpu == this_cpu ? '*' : ' '), cpu,
+                      pp->pcr[0], pp->pcr[1], pp->pcr[2], pp->pcr[3],
+                      pp->pic[0], pp->pic[1], pp->pic[2], pp->pic[3]);
+       }
+
+       memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot));
+
+       spin_unlock_irqrestore(&global_cpu_snapshot_lock, flags);
+}
+
+static void sysrq_handle_globpmu(int key)
+{
+       pmu_snapshot_all_cpus();
+}
+
+static struct sysrq_key_op sparc_globalpmu_op = {
+       .handler        = sysrq_handle_globpmu,
+       .help_msg       = "global-pmu(X)",
+       .action_msg     = "Show Global PMU Regs",
+};
+
+static int __init sparc_sysrq_init(void)
+{
+       int ret = register_sysrq_key('y', &sparc_globalreg_op);
+
+       if (!ret)
+               ret = register_sysrq_key('x', &sparc_globalpmu_op);
+       return ret;
+}
+
+core_initcall(sparc_sysrq_init);
 
 #endif
 
@@ -372,13 +452,16 @@ void flush_thread(void)
 /* It's a bit more tricky when 64-bit tasks are involved... */
 static unsigned long clone_stackframe(unsigned long csp, unsigned long psp)
 {
+       bool stack_64bit = test_thread_64bit_stack(psp);
        unsigned long fp, distance, rval;
 
-       if (!(test_thread_flag(TIF_32BIT))) {
+       if (stack_64bit) {
                csp += STACK_BIAS;
                psp += STACK_BIAS;
                __get_user(fp, &(((struct reg_window __user *)psp)->ins[6]));
                fp += STACK_BIAS;
+               if (test_thread_flag(TIF_32BIT))
+                       fp &= 0xffffffff;
        } else
                __get_user(fp, &(((struct reg_window32 __user *)psp)->ins[6]));
 
@@ -392,7 +475,7 @@ static unsigned long clone_stackframe(unsigned long csp, unsigned long psp)
        rval = (csp - distance);
        if (copy_in_user((void __user *) rval, (void __user *) psp, distance))
                rval = 0;
-       else if (test_thread_flag(TIF_32BIT)) {
+       else if (!stack_64bit) {
                if (put_user(((u32)csp),
                             &(((struct reg_window32 __user *)rval)->ins[6])))
                        rval = 0;
@@ -427,18 +510,18 @@ void synchronize_user_stack(void)
 
        flush_user_windows();
        if ((window = get_thread_wsaved()) != 0) {
-               int winsize = sizeof(struct reg_window);
-               int bias = 0;
-
-               if (test_thread_flag(TIF_32BIT))
-                       winsize = sizeof(struct reg_window32);
-               else
-                       bias = STACK_BIAS;
-
                window -= 1;
                do {
-                       unsigned long sp = (t->rwbuf_stkptrs[window] + bias);
                        struct reg_window *rwin = &t->reg_window[window];
+                       int winsize = sizeof(struct reg_window);
+                       unsigned long sp;
+
+                       sp = t->rwbuf_stkptrs[window];
+
+                       if (test_thread_64bit_stack(sp))
+                               sp += STACK_BIAS;
+                       else
+                               winsize = sizeof(struct reg_window32);
 
                        if (!copy_to_user((char __user *)sp, rwin, winsize)) {
                                shift_window_buffer(window, get_thread_wsaved() - 1, t);
@@ -464,13 +547,6 @@ void fault_in_user_windows(void)
 {
        struct thread_info *t = current_thread_info();
        unsigned long window;
-       int winsize = sizeof(struct reg_window);
-       int bias = 0;
-
-       if (test_thread_flag(TIF_32BIT))
-               winsize = sizeof(struct reg_window32);
-       else
-               bias = STACK_BIAS;
 
        flush_user_windows();
        window = get_thread_wsaved();
@@ -478,8 +554,16 @@ void fault_in_user_windows(void)
        if (likely(window != 0)) {
                window -= 1;
                do {
-                       unsigned long sp = (t->rwbuf_stkptrs[window] + bias);
                        struct reg_window *rwin = &t->reg_window[window];
+                       int winsize = sizeof(struct reg_window);
+                       unsigned long sp;
+
+                       sp = t->rwbuf_stkptrs[window];
+
+                       if (test_thread_64bit_stack(sp))
+                               sp += STACK_BIAS;
+                       else
+                               winsize = sizeof(struct reg_window32);
 
                        if (unlikely(sp & 0x7UL))
                                stack_unaligned(sp);
index 484daba..7ff45e4 100644 (file)
@@ -151,7 +151,7 @@ static int regwindow64_get(struct task_struct *target,
 {
        unsigned long rw_addr = regs->u_regs[UREG_I6];
 
-       if (test_tsk_thread_flag(current, TIF_32BIT)) {
+       if (!test_thread_64bit_stack(rw_addr)) {
                struct reg_window32 win32;
                int i;
 
@@ -176,7 +176,7 @@ static int regwindow64_set(struct task_struct *target,
 {
        unsigned long rw_addr = regs->u_regs[UREG_I6];
 
-       if (test_tsk_thread_flag(current, TIF_32BIT)) {
+       if (!test_thread_64bit_stack(rw_addr)) {
                struct reg_window32 win32;
                int i;
 
index 0800e71..0eaf005 100644 (file)
@@ -316,6 +316,25 @@ static void __init popc_patch(void)
        }
 }
 
+static void __init pause_patch(void)
+{
+       struct pause_patch_entry *p;
+
+       p = &__pause_3insn_patch;
+       while (p < &__pause_3insn_patch_end) {
+               unsigned long i, addr = p->addr;
+
+               for (i = 0; i < 3; i++) {
+                       *(unsigned int *) (addr +  (i * 4)) = p->insns[i];
+                       wmb();
+                       __asm__ __volatile__("flush     %0"
+                                            : : "r" (addr +  (i * 4)));
+               }
+
+               p++;
+       }
+}
+
 #ifdef CONFIG_SMP
 void __init boot_cpu_id_too_large(int cpu)
 {
@@ -528,6 +547,8 @@ static void __init init_sparc64_elf_hwcap(void)
 
        if (sparc64_elf_hwcap & AV_SPARC_POPC)
                popc_patch();
+       if (sparc64_elf_hwcap & AV_SPARC_PAUSE)
+               pause_patch();
 }
 
 void __init setup_arch(char **cmdline_p)
index 867de2f..689e1ba 100644 (file)
@@ -295,9 +295,7 @@ void do_rt_sigreturn(struct pt_regs *regs)
                err |= restore_fpu_state(regs, fpu_save);
 
        err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t));
-       err |= do_sigaltstack(&sf->stack, NULL, (unsigned long)sf);
-
-       if (err)
+       if (err || do_sigaltstack(&sf->stack, NULL, (unsigned long)sf) == -EFAULT)
                goto segv;
 
        err |= __get_user(rwin_save, &sf->rwin_save);
index 781bcb1..d94b878 100644 (file)
@@ -852,6 +852,8 @@ extern unsigned long xcall_flush_tlb_mm;
 extern unsigned long xcall_flush_tlb_pending;
 extern unsigned long xcall_flush_tlb_kernel_range;
 extern unsigned long xcall_fetch_glob_regs;
+extern unsigned long xcall_fetch_glob_pmu;
+extern unsigned long xcall_fetch_glob_pmu_n4;
 extern unsigned long xcall_receive_signal;
 extern unsigned long xcall_new_mmu_context_version;
 #ifdef CONFIG_KGDB
@@ -1000,6 +1002,15 @@ void smp_fetch_global_regs(void)
        smp_cross_call(&xcall_fetch_glob_regs, 0, 0, 0);
 }
 
+void smp_fetch_global_pmu(void)
+{
+       if (tlb_type == hypervisor &&
+           sun4v_chip_type >= SUN4V_CHIP_NIAGARA4)
+               smp_cross_call(&xcall_fetch_glob_pmu_n4, 0, 0, 0);
+       else
+               smp_cross_call(&xcall_fetch_glob_pmu, 0, 0, 0);
+}
+
 /* We know that the window frames of the user have been flushed
  * to the stack before we get here because all callers of us
  * are flush_tlb_*() routines, and these run after flush_cache_*()
index 44025f4..8475a47 100644 (file)
@@ -47,7 +47,7 @@ STUB: sra     REG1, 0, REG1; \
        sra     REG4, 0, REG4
 
 SIGN1(sys32_exit, sparc_exit, %o0)
-SIGN1(sys32_exit_group, sys_exit_group, %o0)
+SIGN1(sys32_exit_group, sparc_exit_group, %o0)
 SIGN1(sys32_wait4, compat_sys_wait4, %o2)
 SIGN1(sys32_creat, sys_creat, %o1)
 SIGN1(sys32_mknod, sys_mknod, %o1)
index 11c6c96..878ef3d 100644 (file)
@@ -751,3 +751,8 @@ int kernel_execve(const char *filename,
                      : "cc");
        return __res;
 }
+
+asmlinkage long sys_kern_features(void)
+{
+       return KERN_FEATURE_MIXED_MODE_STACK;
+}
index 7f5f65d..bf23477 100644 (file)
@@ -118,10 +118,20 @@ ret_from_syscall:
        ba,pt   %xcc, ret_sys_call
         ldx    [%sp + PTREGS_OFF + PT_V9_I0], %o0
 
+       .globl  sparc_exit_group
+       .type   sparc_exit_group,#function
+sparc_exit_group:
+       sethi   %hi(sys_exit_group), %g7
+       ba,pt   %xcc, 1f
+        or     %g7, %lo(sys_exit_group), %g7
+       .size   sparc_exit_group,.-sparc_exit_group
+
        .globl  sparc_exit
        .type   sparc_exit,#function
 sparc_exit:
-       rdpr    %pstate, %g2
+       sethi   %hi(sys_exit), %g7
+       or      %g7, %lo(sys_exit), %g7
+1:     rdpr    %pstate, %g2
        wrpr    %g2, PSTATE_IE, %pstate
        rdpr    %otherwin, %g1
        rdpr    %cansave, %g3
@@ -129,7 +139,7 @@ sparc_exit:
        wrpr    %g3, 0x0, %cansave
        wrpr    %g0, 0x0, %otherwin
        wrpr    %g2, 0x0, %pstate
-       ba,pt   %xcc, sys_exit
+       jmpl    %g7, %g0
         stb    %g0, [%g6 + TI_WSAVED]
        .size   sparc_exit,.-sparc_exit
 
index 63402f9..5147f57 100644 (file)
@@ -85,3 +85,4 @@ sys_call_table:
 /*325*/        .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
 /*330*/        .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
 /*335*/        .long sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
+/*340*/        .long sys_ni_syscall, sys_kcmp
index 3a58e0d..017b74a 100644 (file)
@@ -86,6 +86,7 @@ sys_call_table32:
        .word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init
 /*330*/        .word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime
        .word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev
+/*340*/        .word sys_kern_features, sys_kcmp
 
 #endif /* CONFIG_COMPAT */
 
@@ -132,7 +133,7 @@ sys_call_table:
 /*170*/        .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys_getdents
        .word sys_setsid, sys_fchdir, sys_fgetxattr, sys_listxattr, sys_llistxattr
 /*180*/        .word sys_flistxattr, sys_removexattr, sys_lremovexattr, sys_nis_syscall, sys_ni_syscall
-       .word sys_setpgid, sys_fremovexattr, sys_tkill, sys_exit_group, sys_newuname
+       .word sys_setpgid, sys_fremovexattr, sys_tkill, sparc_exit_group, sys_newuname
 /*190*/        .word sys_init_module, sys_sparc64_personality, sys_remap_file_pages, sys_epoll_create, sys_epoll_ctl
        .word sys_epoll_wait, sys_ioprio_set, sys_getppid, sys_nis_syscall, sys_sgetmask
 /*200*/        .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall
@@ -163,3 +164,4 @@ sys_call_table:
        .word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
 /*330*/        .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
        .word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
+/*340*/        .word sys_kern_features, sys_kcmp
index f81d038..8201c25 100644 (file)
@@ -113,21 +113,24 @@ static inline long sign_extend_imm13(long imm)
 
 static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
 {
-       unsigned long value;
+       unsigned long value, fp;
        
        if (reg < 16)
                return (!reg ? 0 : regs->u_regs[reg]);
+
+       fp = regs->u_regs[UREG_FP];
+
        if (regs->tstate & TSTATE_PRIV) {
                struct reg_window *win;
-               win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+               win = (struct reg_window *)(fp + STACK_BIAS);
                value = win->locals[reg - 16];
-       } else if (test_thread_flag(TIF_32BIT)) {
+       } else if (!test_thread_64bit_stack(fp)) {
                struct reg_window32 __user *win32;
-               win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
+               win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));
                get_user(value, &win32->locals[reg - 16]);
        } else {
                struct reg_window __user *win;
-               win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+               win = (struct reg_window __user *)(fp + STACK_BIAS);
                get_user(value, &win->locals[reg - 16]);
        }
        return value;
@@ -135,19 +138,24 @@ static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
 
 static unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs)
 {
+       unsigned long fp;
+
        if (reg < 16)
                return &regs->u_regs[reg];
+
+       fp = regs->u_regs[UREG_FP];
+
        if (regs->tstate & TSTATE_PRIV) {
                struct reg_window *win;
-               win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+               win = (struct reg_window *)(fp + STACK_BIAS);
                return &win->locals[reg - 16];
-       } else if (test_thread_flag(TIF_32BIT)) {
+       } else if (!test_thread_64bit_stack(fp)) {
                struct reg_window32 *win32;
-               win32 = (struct reg_window32 *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
+               win32 = (struct reg_window32 *)((unsigned long)((u32)fp));
                return (unsigned long *)&win32->locals[reg - 16];
        } else {
                struct reg_window *win;
-               win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+               win = (struct reg_window *)(fp + STACK_BIAS);
                return &win->locals[reg - 16];
        }
 }
@@ -392,13 +400,15 @@ int handle_popc(u32 insn, struct pt_regs *regs)
                if (rd)
                        regs->u_regs[rd] = ret;
        } else {
-               if (test_thread_flag(TIF_32BIT)) {
+               unsigned long fp = regs->u_regs[UREG_FP];
+
+               if (!test_thread_64bit_stack(fp)) {
                        struct reg_window32 __user *win32;
-                       win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
+                       win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));
                        put_user(ret, &win32->locals[rd - 16]);
                } else {
                        struct reg_window __user *win;
-                       win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+                       win = (struct reg_window __user *)(fp + STACK_BIAS);
                        put_user(ret, &win->locals[rd - 16]);
                }
        }
@@ -554,7 +564,7 @@ void handle_ld_nf(u32 insn, struct pt_regs *regs)
                reg[0] = 0;
                if ((insn & 0x780000) == 0x180000)
                        reg[1] = 0;
-       } else if (test_thread_flag(TIF_32BIT)) {
+       } else if (!test_thread_64bit_stack(regs->u_regs[UREG_FP])) {
                put_user(0, (int __user *) reg);
                if ((insn & 0x780000) == 0x180000)
                        put_user(0, ((int __user *) reg) + 1);
index 08e074b..c096c62 100644 (file)
@@ -149,21 +149,24 @@ static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,
 
 static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
 {
-       unsigned long value;
+       unsigned long value, fp;
        
        if (reg < 16)
                return (!reg ? 0 : regs->u_regs[reg]);
+
+       fp = regs->u_regs[UREG_FP];
+
        if (regs->tstate & TSTATE_PRIV) {
                struct reg_window *win;
-               win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+               win = (struct reg_window *)(fp + STACK_BIAS);
                value = win->locals[reg - 16];
-       } else if (test_thread_flag(TIF_32BIT)) {
+       } else if (!test_thread_64bit_stack(fp)) {
                struct reg_window32 __user *win32;
-               win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
+               win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));
                get_user(value, &win32->locals[reg - 16]);
        } else {
                struct reg_window __user *win;
-               win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+               win = (struct reg_window __user *)(fp + STACK_BIAS);
                get_user(value, &win->locals[reg - 16]);
        }
        return value;
@@ -172,16 +175,18 @@ static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
 static inline unsigned long __user *__fetch_reg_addr_user(unsigned int reg,
                                                          struct pt_regs *regs)
 {
+       unsigned long fp = regs->u_regs[UREG_FP];
+
        BUG_ON(reg < 16);
        BUG_ON(regs->tstate & TSTATE_PRIV);
 
-       if (test_thread_flag(TIF_32BIT)) {
+       if (!test_thread_64bit_stack(fp)) {
                struct reg_window32 __user *win32;
-               win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
+               win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));
                return (unsigned long __user *)&win32->locals[reg - 16];
        } else {
                struct reg_window __user *win;
-               win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+               win = (struct reg_window __user *)(fp + STACK_BIAS);
                return &win->locals[reg - 16];
        }
 }
@@ -204,7 +209,7 @@ static void store_reg(struct pt_regs *regs, unsigned long val, unsigned long rd)
        } else {
                unsigned long __user *rd_user = __fetch_reg_addr_user(rd, regs);
 
-               if (test_thread_flag(TIF_32BIT))
+               if (!test_thread_64bit_stack(regs->u_regs[UREG_FP]))
                        __put_user((u32)val, (u32 __user *)rd_user);
                else
                        __put_user(val, rd_user);
index 89c2c29..0bacceb 100644 (file)
@@ -132,6 +132,11 @@ SECTIONS
                *(.popc_6insn_patch)
                __popc_6insn_patch_end = .;
        }
+       .pause_3insn_patch : {
+               __pause_3insn_patch = .;
+               *(.pause_3insn_patch)
+               __pause_3insn_patch_end = .;
+       }
        PERCPU_SECTION(SMP_CACHE_BYTES)
 
        . = ALIGN(PAGE_SIZE);
index a6b0863..1e67ce9 100644 (file)
@@ -43,6 +43,8 @@ spill_fixup_mna:
 spill_fixup_dax:
        TRAP_LOAD_THREAD_REG(%g6, %g1)
        ldx     [%g6 + TI_FLAGS], %g1
+       andcc   %sp, 0x1, %g0
+       movne   %icc, 0, %g1
        andcc   %g1, _TIF_32BIT, %g0
        ldub    [%g6 + TI_WSAVED], %g1
        sll     %g1, 3, %g3
index 4d502da..85c233d 100644 (file)
@@ -1,6 +1,6 @@
 /* atomic.S: These things are too big to do inline.
  *
- * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1999, 2007 2012 David S. Miller (davem@davemloft.net)
  */
 
 #include <linux/linkage.h>
@@ -117,3 +117,17 @@ ENTRY(atomic64_sub_ret) /* %o0 = decrement, %o1 = atomic_ptr */
         sub    %g1, %o0, %o0
 2:     BACKOFF_SPIN(%o2, %o3, 1b)
 ENDPROC(atomic64_sub_ret)
+
+ENTRY(atomic64_dec_if_positive) /* %o0 = atomic_ptr */
+       BACKOFF_SETUP(%o2)
+1:     ldx     [%o0], %g1
+       brlez,pn %g1, 3f
+        sub    %g1, 1, %g7
+       casx    [%o0], %g1, %g7
+       cmp     %g1, %g7
+       bne,pn  %xcc, BACKOFF_LABEL(2f, 1b)
+        nop
+3:     retl
+        sub    %g1, 1, %o0
+2:     BACKOFF_SPIN(%o2, %o3, 1b)
+ENDPROC(atomic64_dec_if_positive)
index ee31b88..0c4e35e 100644 (file)
@@ -116,6 +116,7 @@ EXPORT_SYMBOL(atomic64_add);
 EXPORT_SYMBOL(atomic64_add_ret);
 EXPORT_SYMBOL(atomic64_sub);
 EXPORT_SYMBOL(atomic64_sub_ret);
+EXPORT_SYMBOL(atomic64_dec_if_positive);
 
 /* Atomic bit operations. */
 EXPORT_SYMBOL(test_and_set_bit);
index 1704068..034aadb 100644 (file)
@@ -320,7 +320,7 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f, bool illegal_insn_trap)
                                        XR = 0;
                                else if (freg < 16)
                                        XR = regs->u_regs[freg];
-                               else if (test_thread_flag(TIF_32BIT)) {
+                               else if (!test_thread_64bit_stack(regs->u_regs[UREG_FP])) {
                                        struct reg_window32 __user *win32;
                                        flushw_user ();
                                        win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
index 874162a..f8e13d4 100644 (file)
@@ -481,8 +481,8 @@ xcall_sync_tick:
 
        .globl          xcall_fetch_glob_regs
 xcall_fetch_glob_regs:
-       sethi           %hi(global_reg_snapshot), %g1
-       or              %g1, %lo(global_reg_snapshot), %g1
+       sethi           %hi(global_cpu_snapshot), %g1
+       or              %g1, %lo(global_cpu_snapshot), %g1
        __GET_CPUID(%g2)
        sllx            %g2, 6, %g3
        add             %g1, %g3, %g1
@@ -509,6 +509,66 @@ xcall_fetch_glob_regs:
        stx             %g3, [%g1 + GR_SNAP_THREAD]
        retry
 
+       .globl          xcall_fetch_glob_pmu
+xcall_fetch_glob_pmu:
+       sethi           %hi(global_cpu_snapshot), %g1
+       or              %g1, %lo(global_cpu_snapshot), %g1
+       __GET_CPUID(%g2)
+       sllx            %g2, 6, %g3
+       add             %g1, %g3, %g1
+       rd              %pic, %g7
+       stx             %g7, [%g1 + (4 * 8)]
+       rd              %pcr, %g7
+       stx             %g7, [%g1 + (0 * 8)]
+       retry
+
+       .globl          xcall_fetch_glob_pmu_n4
+xcall_fetch_glob_pmu_n4:
+       sethi           %hi(global_cpu_snapshot), %g1
+       or              %g1, %lo(global_cpu_snapshot), %g1
+       __GET_CPUID(%g2)
+       sllx            %g2, 6, %g3
+       add             %g1, %g3, %g1
+
+       ldxa            [%g0] ASI_PIC, %g7
+       stx             %g7, [%g1 + (4 * 8)]
+       mov             0x08, %g3
+       ldxa            [%g3] ASI_PIC, %g7
+       stx             %g7, [%g1 + (5 * 8)]
+       mov             0x10, %g3
+       ldxa            [%g3] ASI_PIC, %g7
+       stx             %g7, [%g1 + (6 * 8)]
+       mov             0x18, %g3
+       ldxa            [%g3] ASI_PIC, %g7
+       stx             %g7, [%g1 + (7 * 8)]
+
+       mov             %o0, %g2
+       mov             %o1, %g3
+       mov             %o5, %g7
+
+       mov             HV_FAST_VT_GET_PERFREG, %o5
+       mov             3, %o0
+       ta              HV_FAST_TRAP
+       stx             %o1, [%g1 + (3 * 8)]
+       mov             HV_FAST_VT_GET_PERFREG, %o5
+       mov             2, %o0
+       ta              HV_FAST_TRAP
+       stx             %o1, [%g1 + (2 * 8)]
+       mov             HV_FAST_VT_GET_PERFREG, %o5
+       mov             1, %o0
+       ta              HV_FAST_TRAP
+       stx             %o1, [%g1 + (1 * 8)]
+       mov             HV_FAST_VT_GET_PERFREG, %o5
+       mov             0, %o0
+       ta              HV_FAST_TRAP
+       stx             %o1, [%g1 + (0 * 8)]
+
+       mov             %g2, %o0
+       mov             %g3, %o1
+       mov             %g7, %o5
+
+       retry
+
 #ifdef DCACHE_ALIASING_POSSIBLE
        .align          32
        .globl          xcall_flush_dcache_page_cheetah
index 55640cf..3d15364 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 c68808a..6948015 100644 (file)
@@ -1,8 +1,6 @@
 
 header-y += ../arch/
 
-header-y += ucontext.h
-
 generic-y += bug.h
 generic-y += bugs.h
 generic-y += clkdev.h
@@ -37,5 +35,4 @@ generic-y += statfs.h
 generic-y += termbits.h
 generic-y += termios.h
 generic-y += types.h
-generic-y += ucontext.h
 generic-y += xor.h
index 5c6915f..c20db8e 100644 (file)
@@ -15,4 +15,7 @@ header-y += siginfo.h
 header-y += signal.h
 header-y += stat.h
 header-y += swab.h
+header-y += ucontext.h
 header-y += unistd.h
+
+generic-y += ucontext.h
index 001cbfa..243ffeb 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 3a8ece7..0d7103c 100644 (file)
@@ -32,13 +32,14 @@ void flush_thread(void)
                       "err = %d\n", ret);
                force_sig(SIGKILL, current);
        }
+       get_safe_registers(current_pt_regs()->regs.gp,
+                          current_pt_regs()->regs.fp);
 
        __switch_mm(&current->mm->context.id);
 }
 
 void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
 {
-       get_safe_registers(regs->regs.gp, regs->regs.fp);
        PT_REGS_IP(regs) = eip;
        PT_REGS_SP(regs) = esp;
        current->ptrace &= ~PT_DTRACE;
index e5c5473..c4fbb21 100644 (file)
@@ -16,6 +16,8 @@ config UNICORE32
        select ARCH_WANT_FRAME_POINTERS
        select GENERIC_IOMAP
        select MODULES_USE_ELF_REL
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
        help
          UniCore-32 is 32-bit Instruction Set Architecture,
          including a series of low-power-consumption RISC chip
@@ -64,6 +66,9 @@ config GENERIC_CALIBRATE_DELAY
 config ARCH_MAY_HAVE_PC_FDC
        bool
 
+config ZONE_DMA
+       def_bool y
+
 config NEED_DMA_MAP_STATE
        def_bool y
 
@@ -216,7 +221,7 @@ config PUV3_GPIO
        bool
        depends on !ARCH_FPGA
        select GENERIC_GPIO
-       select GPIO_SYSFS if EXPERIMENTAL
+       select GPIO_SYSFS
        default y
 
 if PUV3_NB0916
index c910c98..601e92f 100644 (file)
@@ -1,4 +1,3 @@
-include include/asm-generic/Kbuild.asm
 
 generic-y += atomic.h
 generic-y += auxvec.h
index b1ff8ca..93a56f3 100644 (file)
@@ -19,9 +19,4 @@ extern void die(const char *msg, struct pt_regs *regs, int err);
 extern void uc32_notify_die(const char *str, struct pt_regs *regs,
                struct siginfo *info, unsigned long err, unsigned long trap);
 
-extern asmlinkage void __backtrace(void);
-extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
-
-extern void __show_regs(struct pt_regs *);
-
 #endif /* __UNICORE_BUG_H__ */
index df4d5ac..8e797ad 100644 (file)
@@ -35,7 +35,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
                        : "memory", "cc");
                break;
        default:
-               ret = __xchg_bad_pointer();
+               __xchg_bad_pointer();
        }
 
        return ret;
diff --git a/arch/unicore32/include/asm/kvm_para.h b/arch/unicore32/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 14382cb..4eaa421 100644 (file)
@@ -72,11 +72,6 @@ unsigned long get_wchan(struct task_struct *p);
 
 #define cpu_relax()                    barrier()
 
-/*
- * Create a new kernel thread
- */
-extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
 #define task_pt_regs(p) \
        ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
 
index b9caf9b..726749d 100644 (file)
 #ifndef __UNICORE_PTRACE_H__
 #define __UNICORE_PTRACE_H__
 
-#define PTRACE_GET_THREAD_AREA 22
-
-/*
- * PSR bits
- */
-#define USER_MODE      0x00000010
-#define REAL_MODE      0x00000011
-#define INTR_MODE      0x00000012
-#define PRIV_MODE      0x00000013
-#define ABRT_MODE      0x00000017
-#define EXTN_MODE      0x0000001b
-#define SUSR_MODE      0x0000001f
-#define MODE_MASK      0x0000001f
-#define PSR_R_BIT      0x00000040
-#define PSR_I_BIT      0x00000080
-#define PSR_V_BIT      0x10000000
-#define PSR_C_BIT      0x20000000
-#define PSR_Z_BIT      0x40000000
-#define PSR_S_BIT      0x80000000
-
-/*
- * Groups of PSR bits
- */
-#define PSR_f          0xff000000      /* Flags                */
-#define PSR_c          0x000000ff      /* Control              */
+#include <uapi/asm/ptrace.h>
 
 #ifndef __ASSEMBLY__
 
-/*
- * This struct defines the way the registers are stored on the
- * stack during a system call.  Note that sizeof(struct pt_regs)
- * has to be a multiple of 8.
- */
-struct pt_regs {
-       unsigned long uregs[34];
-};
-
-#define UCreg_asr              uregs[32]
-#define UCreg_pc               uregs[31]
-#define UCreg_lr               uregs[30]
-#define UCreg_sp               uregs[29]
-#define UCreg_ip               uregs[28]
-#define UCreg_fp               uregs[27]
-#define UCreg_26               uregs[26]
-#define UCreg_25               uregs[25]
-#define UCreg_24               uregs[24]
-#define UCreg_23               uregs[23]
-#define UCreg_22               uregs[22]
-#define UCreg_21               uregs[21]
-#define UCreg_20               uregs[20]
-#define UCreg_19               uregs[19]
-#define UCreg_18               uregs[18]
-#define UCreg_17               uregs[17]
-#define UCreg_16               uregs[16]
-#define UCreg_15               uregs[15]
-#define UCreg_14               uregs[14]
-#define UCreg_13               uregs[13]
-#define UCreg_12               uregs[12]
-#define UCreg_11               uregs[11]
-#define UCreg_10               uregs[10]
-#define UCreg_09               uregs[9]
-#define UCreg_08               uregs[8]
-#define UCreg_07               uregs[7]
-#define UCreg_06               uregs[6]
-#define UCreg_05               uregs[5]
-#define UCreg_04               uregs[4]
-#define UCreg_03               uregs[3]
-#define UCreg_02               uregs[2]
-#define UCreg_01               uregs[1]
-#define UCreg_00               uregs[0]
-#define UCreg_ORIG_00          uregs[33]
-
-#ifdef __KERNEL__
-
 #define user_mode(regs)        \
        (processor_mode(regs) == USER_MODE)
 
@@ -125,9 +55,5 @@ static inline int valid_user_regs(struct pt_regs *regs)
 
 #define instruction_pointer(regs)      ((regs)->UCreg_pc)
 
-#endif /* __KERNEL__ */
-
 #endif /* __ASSEMBLY__ */
-
 #endif
-
index baebb3d..0514d7a 100644 (file)
@@ -1,3 +1,10 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += byteorder.h
+header-y += kvm_para.h
+header-y += ptrace.h
+header-y += sigcontext.h
+header-y += unistd.h
+
+generic-y += kvm_para.h
diff --git a/arch/unicore32/include/uapi/asm/ptrace.h b/arch/unicore32/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..187aa2e
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * linux/arch/unicore32/include/asm/ptrace.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 _UAPI__UNICORE_PTRACE_H__
+#define _UAPI__UNICORE_PTRACE_H__
+
+#define PTRACE_GET_THREAD_AREA 22
+
+/*
+ * PSR bits
+ */
+#define USER_MODE      0x00000010
+#define REAL_MODE      0x00000011
+#define INTR_MODE      0x00000012
+#define PRIV_MODE      0x00000013
+#define ABRT_MODE      0x00000017
+#define EXTN_MODE      0x0000001b
+#define SUSR_MODE      0x0000001f
+#define MODE_MASK      0x0000001f
+#define PSR_R_BIT      0x00000040
+#define PSR_I_BIT      0x00000080
+#define PSR_V_BIT      0x10000000
+#define PSR_C_BIT      0x20000000
+#define PSR_Z_BIT      0x40000000
+#define PSR_S_BIT      0x80000000
+
+/*
+ * Groups of PSR bits
+ */
+#define PSR_f          0xff000000      /* Flags                */
+#define PSR_c          0x000000ff      /* Control              */
+
+#ifndef __ASSEMBLY__
+
+/*
+ * This struct defines the way the registers are stored on the
+ * stack during a system call.  Note that sizeof(struct pt_regs)
+ * has to be a multiple of 8.
+ */
+struct pt_regs {
+       unsigned long uregs[34];
+};
+
+#define UCreg_asr              uregs[32]
+#define UCreg_pc               uregs[31]
+#define UCreg_lr               uregs[30]
+#define UCreg_sp               uregs[29]
+#define UCreg_ip               uregs[28]
+#define UCreg_fp               uregs[27]
+#define UCreg_26               uregs[26]
+#define UCreg_25               uregs[25]
+#define UCreg_24               uregs[24]
+#define UCreg_23               uregs[23]
+#define UCreg_22               uregs[22]
+#define UCreg_21               uregs[21]
+#define UCreg_20               uregs[20]
+#define UCreg_19               uregs[19]
+#define UCreg_18               uregs[18]
+#define UCreg_17               uregs[17]
+#define UCreg_16               uregs[16]
+#define UCreg_15               uregs[15]
+#define UCreg_14               uregs[14]
+#define UCreg_13               uregs[13]
+#define UCreg_12               uregs[12]
+#define UCreg_11               uregs[11]
+#define UCreg_10               uregs[10]
+#define UCreg_09               uregs[9]
+#define UCreg_08               uregs[8]
+#define UCreg_07               uregs[7]
+#define UCreg_06               uregs[6]
+#define UCreg_05               uregs[5]
+#define UCreg_04               uregs[4]
+#define UCreg_03               uregs[3]
+#define UCreg_02               uregs[2]
+#define UCreg_01               uregs[1]
+#define UCreg_00               uregs[0]
+#define UCreg_ORIG_00          uregs[33]
+
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _UAPI__UNICORE_PTRACE_H__ */
similarity index 92%
rename from arch/unicore32/include/asm/unistd.h
rename to arch/unicore32/include/uapi/asm/unistd.h
index 2abcf61..d18a3be 100644 (file)
@@ -12,3 +12,4 @@
 
 /* Use the standard ABI for syscalls. */
 #include <asm-generic/unistd.h>
+#define __ARCH_WANT_SYS_EXECVE
index dcb87ab..7049350 100644 (file)
@@ -573,17 +573,16 @@ ENDPROC(ret_to_user)
  */
 ENTRY(ret_from_fork)
        b.l     schedule_tail
-       get_thread_info tsk
-       ldw     r1, [tsk+], #TI_FLAGS           @ check for syscall tracing
-       mov     why, #1
-       cand.a  r1, #_TIF_SYSCALL_TRACE         @ are we tracing syscalls?
-       beq     ret_slow_syscall
-       mov     r1, sp
-       mov     r0, #1                          @ trace exit [IP = 1]
-       b.l     syscall_trace
        b       ret_slow_syscall
 ENDPROC(ret_from_fork)
 
+ENTRY(ret_from_kernel_thread)
+       b.l     schedule_tail
+       mov     r0, r5
+       adr     lr, ret_slow_syscall
+       mov     pc, r4
+ENDPROC(ret_from_kernel_thread)
+
 /*=============================================================================
  * SWI handler
  *-----------------------------------------------------------------------------
@@ -669,11 +668,6 @@ __cr_alignment:
 #endif
        .ltorg
 
-ENTRY(sys_execve)
-               add     r3, sp, #S_OFF
-               b       __sys_execve
-ENDPROC(sys_execve)
-
 ENTRY(sys_clone)
                add     ip, sp, #S_OFF
                stw     ip, [sp+], #4
index b008586..a8fe265 100644 (file)
@@ -258,6 +258,7 @@ void release_thread(struct task_struct *dead_task)
 }
 
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
+asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread");
 
 int
 copy_thread(unsigned long clone_flags, unsigned long stack_start,
@@ -266,17 +267,22 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
        struct thread_info *thread = task_thread_info(p);
        struct pt_regs *childregs = task_pt_regs(p);
 
-       *childregs = *regs;
-       childregs->UCreg_00 = 0;
-       childregs->UCreg_sp = stack_start;
-
        memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save));
        thread->cpu_context.sp = (unsigned long)childregs;
-       thread->cpu_context.pc = (unsigned long)ret_from_fork;
-
-       if (clone_flags & CLONE_SETTLS)
-               childregs->UCreg_16 = regs->UCreg_03;
+       if (unlikely(!regs)) {
+               thread->cpu_context.pc = (unsigned long)ret_from_kernel_thread;
+               thread->cpu_context.r4 = stack_start;
+               thread->cpu_context.r5 = stk_sz;
+               memset(childregs, 0, sizeof(struct pt_regs));
+       } else {
+               thread->cpu_context.pc = (unsigned long)ret_from_fork;
+               *childregs = *regs;
+               childregs->UCreg_00 = 0;
+               childregs->UCreg_sp = stack_start;
 
+               if (clone_flags & CLONE_SETTLS)
+                       childregs->UCreg_16 = regs->UCreg_03;
+       }
        return 0;
 }
 
@@ -305,42 +311,6 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fp)
 }
 EXPORT_SYMBOL(dump_fpu);
 
-/*
- * Shuffle the argument into the correct register before calling the
- * thread function.  r1 is the thread argument, r2 is the pointer to
- * the thread function, and r3 points to the exit function.
- */
-asm(".pushsection .text\n"
-"      .align\n"
-"      .type   kernel_thread_helper, #function\n"
-"kernel_thread_helper:\n"
-"      mov.a   asr, r7\n"
-"      mov     r0, r4\n"
-"      mov     lr, r6\n"
-"      mov     pc, r5\n"
-"      .size   kernel_thread_helper, . - kernel_thread_helper\n"
-"      .popsection");
-
-/*
- * Create a kernel thread.
- */
-pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-       struct pt_regs regs;
-
-       memset(&regs, 0, sizeof(regs));
-
-       regs.UCreg_04 = (unsigned long)arg;
-       regs.UCreg_05 = (unsigned long)fn;
-       regs.UCreg_06 = (unsigned long)do_exit;
-       regs.UCreg_07 = PRIV_MODE;
-       regs.UCreg_pc = (unsigned long)kernel_thread_helper;
-       regs.UCreg_asr = regs.UCreg_07 | PSR_I_BIT;
-
-       return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 unsigned long get_wchan(struct task_struct *p)
 {
        struct stackframe frame;
index f239550..30f749d 100644 (file)
@@ -30,4 +30,10 @@ extern char __vectors_start[], __vectors_end[];
 extern void kernel_thread_helper(void);
 
 extern void __init early_signal_init(void);
+
+extern asmlinkage void __backtrace(void);
+extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
+
+extern void __show_regs(struct pt_regs *);
+
 #endif
index fabdee9..9680134 100644 (file)
@@ -42,69 +42,6 @@ asmlinkage long __sys_clone(unsigned long clone_flags, unsigned long newsp,
                        parent_tid, child_tid);
 }
 
-/* sys_execve() executes a new program.
- * This is called indirectly via a small wrapper
- */
-asmlinkage long __sys_execve(const char __user *filename,
-                         const char __user *const __user *argv,
-                         const char __user *const __user *envp,
-                         struct pt_regs *regs)
-{
-       int error;
-       struct filename *fn;
-
-       fn = getname(filename);
-       error = PTR_ERR(fn);
-       if (IS_ERR(fn))
-               goto out;
-       error = do_execve(fn->name, argv, envp, regs);
-       putname(fn);
-out:
-       return error;
-}
-
-int kernel_execve(const char *filename,
-                 const char *const argv[],
-                 const char *const envp[])
-{
-       struct pt_regs regs;
-       int ret;
-
-       memset(&regs, 0, sizeof(struct pt_regs));
-       ret = do_execve(filename,
-                       (const char __user *const __user *)argv,
-                       (const char __user *const __user *)envp, &regs);
-       if (ret < 0)
-               goto out;
-
-       /*
-        * Save argc to the register structure for userspace.
-        */
-       regs.UCreg_00 = ret;
-
-       /*
-        * We were successful.  We won't be returning to our caller, but
-        * instead to user space by manipulating the kernel stack.
-        */
-       asm("add        r0, %0, %1\n\t"
-               "mov    r1, %2\n\t"
-               "mov    r2, %3\n\t"
-               "mov    r22, #0\n\t"    /* not a syscall */
-               "mov    r23, %0\n\t"    /* thread structure */
-               "b.l    memmove\n\t"    /* copy regs to top of stack */
-               "mov    sp, r0\n\t"     /* reposition stack pointer */
-               "b      ret_to_user"
-               :
-               : "r" (current_thread_info()),
-                 "Ir" (THREAD_START_SP - sizeof(regs)),
-                 "r" (&regs),
-                 "Ir" (sizeof(regs))
-               : "r0", "r1", "r2", "r3", "ip", "lr", "memory");
-
- out:
-       return ret;
-}
-
 /* Note: used by the compat code even in 64-bit Linux. */
 SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
                unsigned long, prot, unsigned long, flags,
index 2eeb9c0..f9b5c10 100644 (file)
@@ -168,7 +168,7 @@ static inline bool access_error(unsigned int fsr, struct vm_area_struct *vma)
 }
 
 static int __do_pf(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
-               struct task_struct *tsk)
+               unsigned int flags, struct task_struct *tsk)
 {
        struct vm_area_struct *vma;
        int fault;
@@ -194,14 +194,7 @@ good_area:
         * If for any reason at all we couldn't handle the fault, make
         * sure we exit gracefully rather than endlessly redo the fault.
         */
-       fault = handle_mm_fault(mm, vma, addr & PAGE_MASK,
-                           (!(fsr ^ 0x12)) ? FAULT_FLAG_WRITE : 0);
-       if (unlikely(fault & VM_FAULT_ERROR))
-               return fault;
-       if (fault & VM_FAULT_MAJOR)
-               tsk->maj_flt++;
-       else
-               tsk->min_flt++;
+       fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, flags);
        return fault;
 
 check_stack:
@@ -216,6 +209,8 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
        struct task_struct *tsk;
        struct mm_struct *mm;
        int fault, sig, code;
+       unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
+                                ((!(fsr ^ 0x12)) ? FAULT_FLAG_WRITE : 0);
 
        tsk = current;
        mm = tsk->mm;
@@ -236,6 +231,7 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
                if (!user_mode(regs)
                    && !search_exception_tables(regs->UCreg_pc))
                        goto no_context;
+retry:
                down_read(&mm->mmap_sem);
        } else {
                /*
@@ -251,7 +247,28 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 #endif
        }
 
-       fault = __do_pf(mm, addr, fsr, tsk);
+       fault = __do_pf(mm, addr, fsr, flags, tsk);
+
+       /* If we need to retry but a fatal signal is pending, handle the
+        * signal first. We do not need to release the mmap_sem because
+        * it would already be released in __lock_page_or_retry in
+        * mm/filemap.c. */
+       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+               return 0;
+
+       if (!(fault & VM_FAULT_ERROR) && (flags & FAULT_FLAG_ALLOW_RETRY)) {
+               if (fault & VM_FAULT_MAJOR)
+                       tsk->maj_flt++;
+               else
+                       tsk->min_flt++;
+               if (fault & VM_FAULT_RETRY) {
+                       /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
+                       * of starvation. */
+                       flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                       goto retry;
+               }
+       }
+
        up_read(&mm->mmap_sem);
 
        /*
index 58790bd..05afcca 100644 (file)
@@ -142,7 +142,7 @@ KBUILD_CFLAGS += $(call cc-option,-mno-avx,)
 KBUILD_CFLAGS += $(mflags-y)
 KBUILD_AFLAGS += $(mflags-y)
 
-archscripts:
+archscripts: scripts_basic
        $(Q)$(MAKE) $(build)=arch/x86/tools relocs
 
 ###
index c760e07..e87b0ca 100644 (file)
@@ -12,6 +12,8 @@
 #include <asm/setup.h>
 #include <asm/desc.h>
 
+#undef memcpy                  /* Use memcpy from misc.c */
+
 #include "eboot.h"
 
 static efi_system_table_t *sys_table;
index 2a01744..8c132a6 100644 (file)
@@ -476,6 +476,3 @@ die:
 setup_corrupt:
        .byte   7
        .string "No setup signature found...\n"
-
-       .data
-dummy: .long   0
index 7c04d0d..1b9c22b 100644 (file)
@@ -515,6 +515,11 @@ static int xts_aesni_setkey(struct crypto_tfm *tfm, const u8 *key,
 }
 
 
+static void aesni_xts_tweak(void *ctx, u8 *out, const u8 *in)
+{
+       aesni_enc(ctx, out, in);
+}
+
 static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
                       struct scatterlist *src, unsigned int nbytes)
 {
@@ -525,7 +530,7 @@ static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
                .tbuflen = sizeof(buf),
 
                .tweak_ctx = aes_ctx(ctx->raw_tweak_ctx),
-               .tweak_fn = XTS_TWEAK_CAST(aesni_enc),
+               .tweak_fn = aesni_xts_tweak,
                .crypt_ctx = aes_ctx(ctx->raw_crypt_ctx),
                .crypt_fn = lrw_xts_encrypt_callback,
        };
@@ -550,7 +555,7 @@ static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
                .tbuflen = sizeof(buf),
 
                .tweak_ctx = aes_ctx(ctx->raw_tweak_ctx),
-               .tweak_fn = XTS_TWEAK_CAST(aesni_enc),
+               .tweak_fn = aesni_xts_tweak,
                .crypt_ctx = aes_ctx(ctx->raw_crypt_ctx),
                .crypt_fn = lrw_xts_decrypt_callback,
        };
index 66e5f0e..79fd8a3 100644 (file)
@@ -12,6 +12,7 @@ header-y += mce.h
 header-y += msr-index.h
 header-y += msr.h
 header-y += mtrr.h
+header-y += perf_regs.h
 header-y += posix_types_32.h
 header-y += posix_types_64.h
 header-y += posix_types_x32.h
@@ -19,8 +20,10 @@ header-y += prctl.h
 header-y += processor-flags.h
 header-y += ptrace-abi.h
 header-y += sigcontext32.h
+header-y += svm.h
 header-y += ucontext.h
 header-y += vm86.h
+header-y += vmx.h
 header-y += vsyscall.h
 
 genhdr-y += unistd_32.h
index 93e1c55..03dd729 100644 (file)
@@ -2,9 +2,6 @@
 #define _ASM_X86_DEVICE_H
 
 struct dev_archdata {
-#ifdef CONFIG_ACPI
-       void    *acpi_handle;
-#endif
 #ifdef CONFIG_X86_DEV_DMA_OPS
        struct dma_map_ops *dma_ops;
 #endif
index c9dcc18..6e8fdf5 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,8 @@ 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_unmap_memmap(void);
+extern void efi_memory_uc(u64 addr, unsigned long size);
 
 #ifndef CONFIG_EFI
 /*
index 831dbb9..41ab26e 100644 (file)
@@ -399,14 +399,17 @@ static inline void drop_init_fpu(struct task_struct *tsk)
 typedef struct { int preload; } fpu_switch_t;
 
 /*
- * FIXME! We could do a totally lazy restore, but we need to
- * add a per-cpu "this was the task that last touched the FPU
- * on this CPU" variable, and the task needs to have a "I last
- * touched the FPU on this CPU" and check them.
+ * Must be run with preemption disabled: this clears the fpu_owner_task,
+ * on this CPU.
  *
- * We don't do that yet, so "fpu_lazy_restore()" always returns
- * false, but some day..
+ * This will disable any lazy FPU state restore of the current FPU state,
+ * but if the current thread owns the FPU, it will still be saved by.
  */
+static inline void __cpu_disable_lazy_restore(unsigned int cpu)
+{
+       per_cpu(fpu_owner_task, cpu) = NULL;
+}
+
 static inline int fpu_lazy_restore(struct task_struct *new, unsigned int cpu)
 {
        return new == this_cpu_read_stable(fpu_owner_task) &&
index dcfde52..19f16eb 100644 (file)
@@ -205,21 +205,14 @@ static inline bool user_64bit_mode(struct pt_regs *regs)
 }
 #endif
 
-/*
- * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode
- * when it traps.  The previous stack will be directly underneath the saved
- * registers, and 'sp/ss' won't even have been saved. Thus the '&regs->sp'.
- *
- * This is valid only for kernel mode traps.
- */
-static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
-{
 #ifdef CONFIG_X86_32
-       return (unsigned long)(&regs->sp);
+extern unsigned long kernel_stack_pointer(struct pt_regs *regs);
 #else
+static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
+{
        return regs->sp;
-#endif
 }
+#endif
 
 #define GET_IP(regs) ((regs)->ip)
 #define GET_FP(regs) ((regs)->bp)
index 59c226d..c20d1ce 100644 (file)
@@ -359,18 +359,14 @@ HYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val,
                return _hypercall4(int, update_va_mapping, va,
                                   new_val.pte, new_val.pte >> 32, flags);
 }
+extern int __must_check xen_event_channel_op_compat(int, void *);
 
 static inline int
 HYPERVISOR_event_channel_op(int cmd, void *arg)
 {
        int rc = _hypercall2(int, event_channel_op, cmd, arg);
-       if (unlikely(rc == -ENOSYS)) {
-               struct evtchn_op op;
-               op.cmd = cmd;
-               memcpy(&op.u, arg, sizeof(op.u));
-               rc = _hypercall1(int, event_channel_op_compat, &op);
-               memcpy(arg, &op.u, sizeof(op.u));
-       }
+       if (unlikely(rc == -ENOSYS))
+               rc = xen_event_channel_op_compat(cmd, arg);
        return rc;
 }
 
@@ -386,17 +382,14 @@ HYPERVISOR_console_io(int cmd, int count, char *str)
        return _hypercall3(int, console_io, cmd, count, str);
 }
 
+extern int __must_check HYPERVISOR_physdev_op_compat(int, void *);
+
 static inline int
 HYPERVISOR_physdev_op(int cmd, void *arg)
 {
        int rc = _hypercall2(int, physdev_op, cmd, arg);
-       if (unlikely(rc == -ENOSYS)) {
-               struct physdev_op op;
-               op.cmd = cmd;
-               memcpy(&op.u, arg, sizeof(op.u));
-               rc = _hypercall1(int, physdev_op_compat, &op);
-               memcpy(arg, &op.u, sizeof(op.u));
-       }
+       if (unlikely(rc == -ENOSYS))
+               rc = HYPERVISOR_physdev_op_compat(cmd, arg);
        return rc;
 }
 
index 66d0fff..125f344 100644 (file)
@@ -33,7 +33,6 @@
 #ifndef _ASM_X86_XEN_HYPERVISOR_H
 #define _ASM_X86_XEN_HYPERVISOR_H
 
-/* arch/i386/kernel/setup.c */
 extern struct shared_info *HYPERVISOR_shared_info;
 extern struct start_info *xen_start_info;
 
index 6d2f75a..54d52ff 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);
index e651f7a..e48cafc 100644 (file)
@@ -574,6 +574,12 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
 
        return irq;
 }
+EXPORT_SYMBOL_GPL(acpi_register_gsi);
+
+void acpi_unregister_gsi(u32 gsi)
+{
+}
+EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
 
 void __init acpi_set_irq_model_pic(void)
 {
index 11676cf..d5e0d71 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 c265593..1817fa9 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 f7e98a2..1b7d165 100644 (file)
@@ -631,6 +631,20 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
                }
        }
 
+       /*
+        * The way access filter has a performance penalty on some workloads.
+        * Disable it on the affected CPUs.
+        */
+       if ((c->x86 == 0x15) &&
+           (c->x86_model >= 0x02) && (c->x86_model < 0x20)) {
+               u64 val;
+
+               if (!rdmsrl_safe(0xc0011021, &val) && !(val & 0x1E)) {
+                       val |= 0x1E;
+                       wrmsrl_safe(0xc0011021, val);
+               }
+       }
+
        cpu_detect_cache_sizes(c);
 
        /* Multi core CPU? */
index 9a7c90d..93c5451 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 29e87d3..46cbf86 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 c4e916d..1ac581f 100644 (file)
@@ -6,7 +6,7 @@
  *
  *  Written by Jacob Shin - AMD, Inc.
  *
- *  Support: borislav.petkov@amd.com
+ *  Maintained by: Borislav Petkov <bp@alien8.de>
  *
  *  April 2006
  *     - added support for AMD Family 0x10 processors
@@ -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 5f88abf..4f9a3cb 100644 (file)
@@ -285,34 +285,39 @@ void cmci_clear(void)
        raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
 }
 
+static long cmci_rediscover_work_func(void *arg)
+{
+       int banks;
+
+       /* Recheck banks in case CPUs don't all have the same */
+       if (cmci_supported(&banks))
+               cmci_discover(banks);
+
+       return 0;
+}
+
 /*
  * After a CPU went down cycle through all the others and rediscover
  * Must run in process context.
  */
 void cmci_rediscover(int dying)
 {
-       int banks;
-       int cpu;
-       cpumask_var_t old;
+       int cpu, banks;
 
        if (!cmci_supported(&banks))
                return;
-       if (!alloc_cpumask_var(&old, GFP_KERNEL))
-               return;
-       cpumask_copy(old, &current->cpus_allowed);
 
        for_each_online_cpu(cpu) {
                if (cpu == dying)
                        continue;
-               if (set_cpus_allowed_ptr(current, cpumask_of(cpu)))
+
+               if (cpu == smp_processor_id()) {
+                       cmci_rediscover_work_func(NULL);
                        continue;
-               /* Recheck banks in case CPUs don't all have the same */
-               if (cmci_supported(&banks))
-                       cmci_discover(banks);
-       }
+               }
 
-       set_cpus_allowed_ptr(current, old);
-       free_cpumask_var(old);
+               work_on_cpu(cpu, cmci_rediscover_work_func, NULL);
+       }
 }
 
 /*
index 915b876..4a3374e 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++;
index 99d96a4..3cf3d97 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 7c46bfd..4b7731b 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 e4dd0f7..7d0270b 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);
 }
@@ -158,5 +251,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 ed858e9..df06ade 100644 (file)
@@ -1077,6 +1077,9 @@ void __init memblock_x86_fill(void)
                memblock_add(ei->addr, ei->size);
        }
 
+       /* throw away partial pages */
+       memblock_trim_memory(PAGE_SIZE);
+
        memblock_dump_all();
 }
 
index a1193ae..88b725a 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 0c58952..1328fe4 100644 (file)
@@ -995,8 +995,8 @@ END(interrupt)
         */
        .p2align CONFIG_X86_L1_CACHE_SHIFT
 common_interrupt:
-       ASM_CLAC
        XCPT_FRAME
+       ASM_CLAC
        addq $-0x80,(%rsp)              /* Adjust vector to [-256,-1] range */
        interrupt do_IRQ
        /* 0(%rsp): old_rsp-ARGOFFSET */
@@ -1135,8 +1135,8 @@ END(common_interrupt)
  */
 .macro apicinterrupt num sym do_sym
 ENTRY(\sym)
-       ASM_CLAC
        INTR_FRAME
+       ASM_CLAC
        pushq_cfi $~(\num)
 .Lcommon_\sym:
        interrupt \do_sym
@@ -1190,8 +1190,8 @@ apicinterrupt IRQ_WORK_VECTOR \
  */
 .macro zeroentry sym do_sym
 ENTRY(\sym)
-       ASM_CLAC
        INTR_FRAME
+       ASM_CLAC
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        pushq_cfi $-1           /* ORIG_RAX: no syscall to restart */
        subq $ORIG_RAX-R15, %rsp
@@ -1208,8 +1208,8 @@ END(\sym)
 
 .macro paranoidzeroentry sym do_sym
 ENTRY(\sym)
-       ASM_CLAC
        INTR_FRAME
+       ASM_CLAC
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        pushq_cfi $-1           /* ORIG_RAX: no syscall to restart */
        subq $ORIG_RAX-R15, %rsp
@@ -1227,8 +1227,8 @@ END(\sym)
 #define INIT_TSS_IST(x) PER_CPU_VAR(init_tss) + (TSS_ist + ((x) - 1) * 8)
 .macro paranoidzeroentry_ist sym do_sym ist
 ENTRY(\sym)
-       ASM_CLAC
        INTR_FRAME
+       ASM_CLAC
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        pushq_cfi $-1           /* ORIG_RAX: no syscall to restart */
        subq $ORIG_RAX-R15, %rsp
@@ -1247,8 +1247,8 @@ END(\sym)
 
 .macro errorentry sym do_sym
 ENTRY(\sym)
-       ASM_CLAC
        XCPT_FRAME
+       ASM_CLAC
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        subq $ORIG_RAX-R15, %rsp
        CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
@@ -1266,8 +1266,8 @@ END(\sym)
        /* error code is on the stack already */
 .macro paranoiderrorentry sym do_sym
 ENTRY(\sym)
-       ASM_CLAC
        XCPT_FRAME
+       ASM_CLAC
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        subq $ORIG_RAX-R15, %rsp
        CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
@@ -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 957a47a..4dac2f6 100644 (file)
@@ -292,8 +292,8 @@ default_entry:
  *     be using the global pages. 
  *
  *     NOTE! If we are on a 486 we may have no cr4 at all!
- *     Specifically, cr4 exists if and only if CPUID exists,
- *     which in turn exists if and only if EFLAGS.ID exists.
+ *     Specifically, cr4 exists if and only if CPUID exists
+ *     and has flags other than the FPU flag set.
  */
        movl $X86_EFLAGS_ID,%ecx
        pushl %ecx
@@ -308,6 +308,11 @@ default_entry:
        testl %ecx,%eax
        jz 6f                   # No ID flag = no CPUID = no CR4
 
+       movl $1,%eax
+       cpuid
+       andl $~1,%edx           # Ignore CPUID.FPU
+       jz 6f                   # No flags or only CPUID.FPU = no CR4
+
        movl pa(mmu_cr4_features),%eax
        movl %eax,%cr4
 
index b3e5e51..4180a87 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 7720ff5..efdec7c 100644 (file)
@@ -8,8 +8,8 @@
  *  Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
  *
  *  Maintainers:
- *  Andreas Herrmann <andreas.herrmann3@amd.com>
- *  Borislav Petkov <borislav.petkov@amd.com>
+ *  Andreas Herrmann <herrmann.der.user@googlemail.com>
+ *  Borislav Petkov <bp@alien8.de>
  *
  *  This driver allows to upgrade microcode on F10h AMD
  *  CPUs and later.
@@ -190,6 +190,7 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size,
 #define F1XH_MPB_MAX_SIZE 2048
 #define F14H_MPB_MAX_SIZE 1824
 #define F15H_MPB_MAX_SIZE 4096
+#define F16H_MPB_MAX_SIZE 3458
 
        switch (c->x86) {
        case 0x14:
@@ -198,6 +199,9 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size,
        case 0x15:
                max_size = F15H_MPB_MAX_SIZE;
                break;
+       case 0x16:
+               max_size = F16H_MPB_MAX_SIZE;
+               break;
        default:
                max_size = F1XH_MPB_MAX_SIZE;
                break;
index b00b33a..974b67e 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/perf_event.h>
 #include <linux/hw_breakpoint.h>
 #include <linux/rcupdate.h>
+#include <linux/module.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -166,6 +167,35 @@ static inline bool invalid_selector(u16 value)
 
 #define FLAG_MASK              FLAG_MASK_32
 
+/*
+ * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode
+ * when it traps.  The previous stack will be directly underneath the saved
+ * registers, and 'sp/ss' won't even have been saved. Thus the '&regs->sp'.
+ *
+ * Now, if the stack is empty, '&regs->sp' is out of range. In this
+ * case we try to take the previous stack. To always return a non-null
+ * stack pointer we fall back to regs as stack if no previous stack
+ * exists.
+ *
+ * This is valid only for kernel mode traps.
+ */
+unsigned long kernel_stack_pointer(struct pt_regs *regs)
+{
+       unsigned long context = (unsigned long)regs & ~(THREAD_SIZE - 1);
+       unsigned long sp = (unsigned long)&regs->sp;
+       struct thread_info *tinfo;
+
+       if (context == (sp & ~(THREAD_SIZE - 1)))
+               return sp;
+
+       tinfo = (struct thread_info *)context;
+       if (tinfo->previous_esp)
+               return tinfo->previous_esp;
+
+       return (unsigned long)regs;
+}
+EXPORT_SYMBOL_GPL(kernel_stack_pointer);
+
 static unsigned long *pt_regs_access(struct pt_regs *regs, unsigned long regno)
 {
        BUILD_BUG_ON(offsetof(struct pt_regs, bx) != 0);
@@ -1511,6 +1541,13 @@ void syscall_trace_leave(struct pt_regs *regs)
 {
        bool step;
 
+       /*
+        * We may come here right after calling schedule_user()
+        * or do_notify_resume(), in which case we can be in RCU
+        * user mode.
+        */
+       rcu_user_exit();
+
        audit_syscall_exit(regs);
 
        if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
index 52190a9..4e8ba39 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 a2bb18e..ca45696 100644 (file)
@@ -920,8 +920,22 @@ 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;
+               unsigned long start, end;
+               unsigned long start_pfn, end_pfn;
+
+               for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn,
+                                                        NULL) {
+
+                       end = PFN_PHYS(end_pfn);
+                       if (end <= (1UL<<32))
+                               continue;
+
+                       start = PFN_PHYS(start_pfn);
+                       max_pfn_mapped = init_memory_mapping(
+                                               max((1UL<<32), start), end);
+               }
+
                /* can we preseve max_low_pfn ?*/
                max_low_pfn = max_pfn;
        }
@@ -1035,6 +1049,18 @@ void __init setup_arch(char **cmdline_p)
        arch_init_ideal_nops();
 
        register_refined_jiffies(CLOCK_TICK_RATE);
+
+#ifdef CONFIG_EFI
+       /* Once setup is done above, disable efi_enabled on mismatched
+        * firmware/kernel archtectures since there is no support for
+        * runtime services.
+        */
+       if (efi_enabled && IS_ENABLED(CONFIG_X86_64) != efi_64bit) {
+               pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n");
+               efi_unmap_memmap();
+               efi_enabled = 0;
+       }
+#endif
 }
 
 #ifdef CONFIG_X86_32
index 29ad351..70b27ee 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 c80a33b..f3e2ec8 100644 (file)
@@ -68,6 +68,8 @@
 #include <asm/mwait.h>
 #include <asm/apic.h>
 #include <asm/io_apic.h>
+#include <asm/i387.h>
+#include <asm/fpu-internal.h>
 #include <asm/setup.h>
 #include <asm/uv/uv.h>
 #include <linux/mc146818rtc.h>
@@ -818,6 +820,9 @@ int __cpuinit native_cpu_up(unsigned int cpu, struct task_struct *tidle)
 
        per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
 
+       /* the FPU context is blank, nobody can own it */
+       __cpu_disable_lazy_restore(cpu);
+
        err = do_boot_cpu(apicid, cpu, tidle);
        if (err) {
                pr_debug("do_boot_cpu failed %d\n", err);
index 9538f00..aafa555 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 a10e460..58fc514 100644 (file)
@@ -24,6 +24,9 @@ static inline bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpuid_entry2 *best;
 
+       if (!static_cpu_has(X86_FEATURE_XSAVE))
+               return 0;
+
        best = kvm_find_cpuid_entry(vcpu, 1, 0);
        return best && (best->ecx & bit(X86_FEATURE_XSAVE));
 }
index 39171cb..bba39bf 100644 (file)
@@ -426,8 +426,7 @@ static void invalidate_registers(struct x86_emulate_ctxt *ctxt)
                        _ASM_EXTABLE(1b, 3b)                            \
                        : "=m" ((ctxt)->eflags), "=&r" (_tmp),          \
                          "+a" (*rax), "+d" (*rdx), "+qm"(_ex)          \
-                       : "i" (EFLAGS_MASK), "m" ((ctxt)->src.val),     \
-                         "a" (*rax), "d" (*rdx));                      \
+                       : "i" (EFLAGS_MASK), "m" ((ctxt)->src.val));    \
        } while (0)
 
 /* instruction has only one source operand, destination is implicit (e.g. mul, div, imul, idiv) */
index c6e6b72..43e9fad 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 d289fee..6f85fe0 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 ad6b1dd..f858159 100644 (file)
@@ -6549,19 +6549,22 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
                }
        }
 
-       exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
        /* Exposing INVPCID only when PCID is exposed */
        best = kvm_find_cpuid_entry(vcpu, 0x7, 0);
        if (vmx_invpcid_supported() &&
            best && (best->ebx & bit(X86_FEATURE_INVPCID)) &&
            guest_cpuid_has_pcid(vcpu)) {
+               exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
                exec_control |= SECONDARY_EXEC_ENABLE_INVPCID;
                vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
                             exec_control);
        } else {
-               exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID;
-               vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
-                            exec_control);
+               if (cpu_has_secondary_exec_ctrls()) {
+                       exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
+                       exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID;
+                       vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
+                                    exec_control);
+               }
                if (best)
                        best->ebx &= ~bit(X86_FEATURE_INVPCID);
        }
index 1eefebe..4f76417 100644 (file)
@@ -3779,7 +3779,7 @@ static int write_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa,
 {
        struct kvm_mmio_fragment *frag = &vcpu->mmio_fragments[0];
 
-       memcpy(vcpu->run->mmio.data, frag->data, frag->len);
+       memcpy(vcpu->run->mmio.data, frag->data, min(8u, frag->len));
        return X86EMUL_CONTINUE;
 }
 
@@ -3832,18 +3832,11 @@ mmio:
        bytes -= handled;
        val += handled;
 
-       while (bytes) {
-               unsigned now = min(bytes, 8U);
-
-               frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++];
-               frag->gpa = gpa;
-               frag->data = val;
-               frag->len = now;
-
-               gpa += now;
-               val += now;
-               bytes -= now;
-       }
+       WARN_ON(vcpu->mmio_nr_fragments >= KVM_MAX_MMIO_FRAGMENTS);
+       frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++];
+       frag->gpa = gpa;
+       frag->data = val;
+       frag->len = bytes;
        return X86EMUL_CONTINUE;
 }
 
@@ -3890,7 +3883,7 @@ int emulator_read_write(struct x86_emulate_ctxt *ctxt, unsigned long addr,
        vcpu->mmio_needed = 1;
        vcpu->mmio_cur_fragment = 0;
 
-       vcpu->run->mmio.len = vcpu->mmio_fragments[0].len;
+       vcpu->run->mmio.len = min(8u, vcpu->mmio_fragments[0].len);
        vcpu->run->mmio.is_write = vcpu->mmio_is_write = ops->write;
        vcpu->run->exit_reason = KVM_EXIT_MMIO;
        vcpu->run->mmio.phys_addr = gpa;
@@ -5522,28 +5515,44 @@ static int complete_emulated_pio(struct kvm_vcpu *vcpu)
  *
  * read:
  *   for each fragment
- *     write gpa, len
- *     exit
- *     copy data
+ *     for each mmio piece in the fragment
+ *       write gpa, len
+ *       exit
+ *       copy data
  *   execute insn
  *
  * write:
  *   for each fragment
- *      write gpa, len
- *      copy data
- *      exit
+ *     for each mmio piece in the fragment
+ *       write gpa, len
+ *       copy data
+ *       exit
  */
 static int complete_emulated_mmio(struct kvm_vcpu *vcpu)
 {
        struct kvm_run *run = vcpu->run;
        struct kvm_mmio_fragment *frag;
+       unsigned len;
 
        BUG_ON(!vcpu->mmio_needed);
 
        /* Complete previous fragment */
-       frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment++];
+       frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment];
+       len = min(8u, frag->len);
        if (!vcpu->mmio_is_write)
-               memcpy(frag->data, run->mmio.data, frag->len);
+               memcpy(frag->data, run->mmio.data, len);
+
+       if (frag->len <= 8) {
+               /* Switch to the next fragment. */
+               frag++;
+               vcpu->mmio_cur_fragment++;
+       } else {
+               /* Go forward to the next mmio piece. */
+               frag->data += len;
+               frag->gpa += len;
+               frag->len -= len;
+       }
+
        if (vcpu->mmio_cur_fragment == vcpu->mmio_nr_fragments) {
                vcpu->mmio_needed = 0;
                if (vcpu->mmio_is_write)
@@ -5551,13 +5560,12 @@ static int complete_emulated_mmio(struct kvm_vcpu *vcpu)
                vcpu->mmio_read_completed = 1;
                return complete_emulated_io(vcpu);
        }
-       /* Initiate next fragment */
-       ++frag;
+
        run->exit_reason = KVM_EXIT_MMIO;
        run->mmio.phys_addr = frag->gpa;
        if (vcpu->mmio_is_write)
-               memcpy(run->mmio.data, frag->data, frag->len);
-       run->mmio.len = frag->len;
+               memcpy(run->mmio.data, frag->data, min(8u, frag->len));
+       run->mmio.len = min(8u, frag->len);
        run->mmio.is_write = vcpu->mmio_is_write;
        vcpu->arch.complete_userspace_io = complete_emulated_mmio;
        return 0;
@@ -5773,6 +5781,9 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        int pending_vec, max_bits, idx;
        struct desc_ptr dt;
 
+       if (!guest_cpuid_has_xsave(vcpu) && (sregs->cr4 & X86_CR4_OSXSAVE))
+               return -EINVAL;
+
        dt.size = sregs->idt.limit;
        dt.address = sregs->idt.base;
        kvm_x86_ops->set_idt(vcpu, &dt);
index ab1f6a9..d7aea41 100644 (file)
@@ -35,40 +35,44 @@ struct map_range {
        unsigned page_size_mask;
 };
 
-static void __init find_early_table_space(struct map_range *mr, unsigned long end,
-                                         int use_pse, int use_gbpages)
+/*
+ * First calculate space needed for kernel direct mapping page tables to cover
+ * mr[0].start to mr[nr_range - 1].end, while accounting for possible 2M and 1GB
+ * pages. Then find enough contiguous space for those page tables.
+ */
+static void __init find_early_table_space(struct map_range *mr, int nr_range)
 {
-       unsigned long puds, pmds, ptes, tables, start = 0, good_end = end;
+       int i;
+       unsigned long puds = 0, pmds = 0, ptes = 0, tables;
+       unsigned long start = 0, good_end;
        phys_addr_t base;
 
-       puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
-       tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
-
-       if (use_gbpages) {
-               unsigned long extra;
-
-               extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT);
-               pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT;
-       } else
-               pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
+       for (i = 0; i < nr_range; i++) {
+               unsigned long range, extra;
 
-       tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE);
+               range = mr[i].end - mr[i].start;
+               puds += (range + PUD_SIZE - 1) >> PUD_SHIFT;
 
-       if (use_pse) {
-               unsigned long extra;
+               if (mr[i].page_size_mask & (1 << PG_LEVEL_1G)) {
+                       extra = range - ((range >> PUD_SHIFT) << PUD_SHIFT);
+                       pmds += (extra + PMD_SIZE - 1) >> PMD_SHIFT;
+               } else {
+                       pmds += (range + PMD_SIZE - 1) >> PMD_SHIFT;
+               }
 
-               extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT);
+               if (mr[i].page_size_mask & (1 << PG_LEVEL_2M)) {
+                       extra = range - ((range >> PMD_SHIFT) << PMD_SHIFT);
 #ifdef CONFIG_X86_32
-               extra += PMD_SIZE;
+                       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;
+                       ptes += (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
+               } else {
+                       ptes += (range + PAGE_SIZE - 1) >> PAGE_SHIFT;
+               }
+       }
 
+       tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
+       tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE);
        tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE);
 
 #ifdef CONFIG_X86_32
@@ -86,7 +90,7 @@ static void __init find_early_table_space(struct map_range *mr, unsigned long en
        pgt_buf_top = pgt_buf_start + (tables >> PAGE_SHIFT);
 
        printk(KERN_DEBUG "kernel direct mapping tables up to %#lx @ [mem %#010lx-%#010lx]\n",
-               end - 1, pgt_buf_start << PAGE_SHIFT,
+               mr[nr_range - 1].end - 1, pgt_buf_start << PAGE_SHIFT,
                (pgt_buf_top << PAGE_SHIFT) - 1);
 }
 
@@ -267,7 +271,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(mr, nr_range);
 
        for (i = 0; i < nr_range; i++)
                ret = kernel_physical_mapping_init(mr[i].start, mr[i].end,
index 2b6b4a3..3baff25 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 0777f04..60f926c 100644 (file)
@@ -197,7 +197,7 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
        }
 
        if (end == TLB_FLUSH_ALL || tlb_flushall_shift == -1
-                                       || vmflag == VM_HUGETLB) {
+                                       || vmflag & VM_HUGETLB) {
                local_flush_tlb();
                goto flush_all;
        }
index 26b8a85..48768df 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 41bd2a2..b914e20 100644 (file)
@@ -115,6 +115,16 @@ static void sata_revid_read(struct sim_dev_reg *reg, u32 *value)
        reg_read(reg, value);
 }
 
+static void reg_noirq_read(struct sim_dev_reg *reg, u32 *value)
+{
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&pci_config_lock, flags);
+       /* force interrupt pin value to 0 */
+       *value = reg->sim_reg.value & 0xfff00ff;
+       raw_spin_unlock_irqrestore(&pci_config_lock, flags);
+}
+
 static struct sim_dev_reg bus1_fixups[] = {
        DEFINE_REG(2, 0, 0x10, (16*MB), reg_init, reg_read, reg_write)
        DEFINE_REG(2, 0, 0x14, (256), reg_init, reg_read, reg_write)
@@ -144,6 +154,7 @@ static struct sim_dev_reg bus1_fixups[] = {
        DEFINE_REG(11, 5, 0x10, (64*KB), reg_init, reg_read, reg_write)
        DEFINE_REG(11, 6, 0x10, (256), reg_init, reg_read, reg_write)
        DEFINE_REG(11, 7, 0x10, (64*KB), reg_init, reg_read, reg_write)
+       DEFINE_REG(11, 7, 0x3c, 256, reg_init, reg_noirq_read, reg_write)
        DEFINE_REG(12, 0, 0x10, (128*KB), reg_init, reg_read, reg_write)
        DEFINE_REG(12, 0, 0x14, (256), reg_init, reg_read, reg_write)
        DEFINE_REG(12, 1, 0x10, (1024), reg_init, reg_read, reg_write)
@@ -161,8 +172,10 @@ static struct sim_dev_reg bus1_fixups[] = {
        DEFINE_REG(16, 0, 0x10, (64*KB), reg_init, reg_read, reg_write)
        DEFINE_REG(16, 0, 0x14, (64*MB), reg_init, reg_read, reg_write)
        DEFINE_REG(16, 0, 0x18, (64*MB), reg_init, reg_read, reg_write)
+       DEFINE_REG(16, 0, 0x3c, 256, reg_init, reg_noirq_read, reg_write)
        DEFINE_REG(17, 0, 0x10, (128*KB), reg_init, reg_read, reg_write)
        DEFINE_REG(18, 0, 0x10, (1*KB), reg_init, reg_read, reg_write)
+       DEFINE_REG(18, 0, 0x3c, 256, reg_init, reg_noirq_read, reg_write)
 };
 
 static void __init init_sim_regs(void)
index 4c61b52..92525cb 100644 (file)
 #include <asm/i8259.h>
 #include <asm/io.h>
 #include <asm/io_apic.h>
+#include <asm/emergency-restart.h>
 
 static int ce4100_i8042_detect(void)
 {
        return 0;
 }
 
+/*
+ * The CE4100 platform has an internal 8051 Microcontroller which is
+ * responsible for signaling to the external Power Management Unit the
+ * intention to reset, reboot or power off the system. This 8051 device has
+ * its command register mapped at I/O port 0xcf9 and the value 0x4 is used
+ * to power off the system.
+ */
+static void ce4100_power_off(void)
+{
+       outb(0x4, 0xcf9);
+}
+
 #ifdef CONFIG_SERIAL_8250
 
 static unsigned int mem_serial_in(struct uart_port *p, int offset)
@@ -139,8 +152,19 @@ void __init x86_ce4100_early_setup(void)
        x86_init.mpparse.find_smp_config = x86_init_noop;
        x86_init.pci.init = ce4100_pci_init;
 
+       /*
+        * By default, the reboot method is ACPI which is supported by the
+        * CE4100 bootloader CEFDK using FADT.ResetReg Address and ResetValue
+        * the bootloader will however issue a system power off instead of
+        * reboot. By using BOOT_KBD we ensure proper system reboot as
+        * expected.
+        */
+       reboot_type = BOOT_KBD;
+
 #ifdef CONFIG_X86_IO_APIC
        x86_init.pci.init_irq = sdv_pci_init;
        x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc_nocheck;
 #endif
+
+       pm_power_off = ce4100_power_off;
 }
index aded2a9..ad44391 100644 (file)
@@ -70,11 +70,15 @@ EXPORT_SYMBOL(efi);
 struct efi_memory_map memmap;
 
 bool efi_64bit;
-static bool efi_native;
 
 static struct efi efi_phys __initdata;
 static efi_system_table_t efi_systab __initdata;
 
+static inline bool efi_is_native(void)
+{
+       return IS_ENABLED(CONFIG_X86_64) == efi_64bit;
+}
+
 static int __init setup_noefi(char *arg)
 {
        efi_enabled = 0;
@@ -420,7 +424,7 @@ void __init efi_reserve_boot_services(void)
        }
 }
 
-static void __init efi_unmap_memmap(void)
+void __init efi_unmap_memmap(void)
 {
        if (memmap.map) {
                early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
@@ -432,7 +436,7 @@ void __init efi_free_boot_services(void)
 {
        void *p;
 
-       if (!efi_native)
+       if (!efi_is_native())
                return;
 
        for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
@@ -684,12 +688,10 @@ void __init efi_init(void)
                return;
        }
        efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab;
-       efi_native = !efi_64bit;
 #else
        efi_phys.systab = (efi_system_table_t *)
                          (boot_params.efi_info.efi_systab |
                          ((__u64)boot_params.efi_info.efi_systab_hi<<32));
-       efi_native = efi_64bit;
 #endif
 
        if (efi_systab_init(efi_phys.systab)) {
@@ -723,7 +725,7 @@ void __init efi_init(void)
         * that doesn't match the kernel 32/64-bit mode.
         */
 
-       if (!efi_native)
+       if (!efi_is_native())
                pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n");
        else if (efi_runtime_init()) {
                efi_enabled = 0;
@@ -735,7 +737,7 @@ void __init efi_init(void)
                return;
        }
 #ifdef CONFIG_X86_32
-       if (efi_native) {
+       if (efi_is_native()) {
                x86_platform.get_wallclock = efi_get_time;
                x86_platform.set_wallclock = efi_set_rtc_mmss;
        }
@@ -810,6 +812,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 +835,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;
 
@@ -834,7 +846,7 @@ void __init efi_enter_virtual_mode(void)
         * non-native EFI
         */
 
-       if (!efi_native) {
+       if (!efi_is_native()) {
                efi_unmap_memmap();
                return;
        }
@@ -879,10 +891,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 +908,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 ac3aa54..95fd505 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 e56479e..9e7e147 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 e3497f2..586d838 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 6226c99..dcf5f2d 100644 (file)
@@ -1288,6 +1288,25 @@ unsigned long xen_read_cr2_direct(void)
        return this_cpu_read(xen_vcpu_info.arch.cr2);
 }
 
+void xen_flush_tlb_all(void)
+{
+       struct mmuext_op *op;
+       struct multicall_space mcs;
+
+       trace_xen_mmu_flush_tlb_all(0);
+
+       preempt_disable();
+
+       mcs = xen_mc_entry(sizeof(*op));
+
+       op = mcs.args;
+       op->cmd = MMUEXT_TLB_FLUSH_ALL;
+       MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
+
+       xen_mc_issue(PARAVIRT_LAZY_MMU);
+
+       preempt_enable();
+}
 static void xen_flush_tlb(void)
 {
        struct mmuext_op *op;
@@ -2518,7 +2537,7 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
        err = 0;
 out:
 
-       flush_tlb_all();
+       xen_flush_tlb_all();
 
        return err;
 }
index cdcb48a..0d1f36a 100644 (file)
@@ -13,6 +13,8 @@ config XTENSA
        select GENERIC_CPU_DEVICES
        select MODULES_USE_ELF_RELA
        select GENERIC_PCI_IOMAP
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
        select ARCH_WANT_OPTIONAL_GPIOLIB
        help
          Xtensa processors are 32-bit RISC machines designed by Tensilica
index 4c316cd..86c34db 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 fccd81e..6d13027 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 b409893..24f50ca 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 376cd9d..569fec4 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 e321490..64dad04 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 75c94a1..677501b 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 e1d8c9e..58c0a4f 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 */
index e6be5b9..700c2e6 100644 (file)
@@ -62,6 +62,10 @@ static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
 static inline void iounmap(volatile void __iomem *addr)
 {
 }
+
+#define virt_to_bus     virt_to_phys
+#define bus_to_virt     phys_to_virt
+
 #endif /* CONFIG_MMU */
 
 /*
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 dae9a8b..f865b1c 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/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 dbd8731..feb10af 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 ba03d5a..0a70e78 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 5c371d8..2d630e7 100644 (file)
@@ -152,6 +152,7 @@ struct thread_struct {
 
 /* Clearing a0 terminates the backtrace. */
 #define start_thread(regs, new_pc, new_sp) \
+       memset(regs, 0, sizeof(*regs)); \
        regs->pc = new_pc; \
        regs->ps = USER_PS_VALUE; \
        regs->areg[1] = new_sp; \
@@ -168,9 +169,6 @@ struct mm_struct;
 /* Free all resources held by a thread. */
 #define release_thread(thread) do { } while(0)
 
-/* Create a kernel thread without removing it from tasklists */
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
 /* Copy and release all segment info associated with a VM */
 #define copy_segments(p, mm)   do { } while(0)
 #define release_segments(mm)   do { } while(0)
index d85d38d..da21c17 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 a3075b1..8a8aa61 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 7f201b9..72fd44c 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 */
-
index c1dacca..124aeee 100644 (file)
@@ -10,7 +10,7 @@
 
 struct pt_regs;
 struct sigaction;
-asmlinkage long xtensa_execve(char*, char**, char**, struct pt_regs*);
+asmlinkage long sys_execve(char*, char**, char**, struct pt_regs*);
 asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*);
 asmlinkage long xtensa_ptrace(long, long, long, long);
 asmlinkage long xtensa_sigreturn(struct pt_regs*);
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 053bc42..175b3d5 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 46d2400..43dd348 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 6d4db7e..2b410b8 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 bc7e005..f4e6eaa 100644 (file)
@@ -1,712 +1,8 @@
-/*
- * 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 - 2005 Tensilica Inc.
- */
-
 #ifndef _XTENSA_UNISTD_H
 #define _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_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__
+#define __ARCH_WANT_SYS_EXECVE
+#include <uapi/asm/unistd.h>
 
 /*
  * "Conditional" syscalls
@@ -735,5 +31,4 @@ __SYSCALL(308, sys_setns, 2)
 #define __IGNORE_vfork                         /* use clone */
 #define __IGNORE_fadvise64                     /* use fadvise64_64 */
 
-#endif /* __KERNEL__ */
-#endif /* _XTENSA_UNISTD_H */
+#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 baebb3d..56aad54 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..9f36d0e
--- /dev/null
@@ -0,0 +1,754 @@
+#if !defined(_UAPI_XTENSA_UNISTD_H) || defined(__SYSCALL)
+#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, sys_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 */
+
+#undef __SYSCALL
+
+#endif /* _UAPI_XTENSA_UNISTD_H */
index 33d6e9d..934ae58 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 2bc1e14..54c3be3 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 7e62360..90bfc1d 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
@@ -1833,50 +1833,6 @@ ENTRY(system_call)
 
 
 /*
- * Create a kernel thread
- *
- * int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
- * a2                    a2                 a3             a4
- */
-
-ENTRY(kernel_thread)
-       entry   a1, 16
-
-       mov     a5, a2                  # preserve fn over syscall
-       mov     a7, a3                  # preserve args over syscall
-
-       movi    a3, _CLONE_VM | _CLONE_UNTRACED
-       movi    a2, __NR_clone
-       or      a6, a4, a3              # arg0: flags
-       mov     a3, a1                  # arg1: sp
-       syscall
-
-       beq     a3, a1, 1f              # branch if parent
-       mov     a6, a7                  # args
-       callx4  a5                      # fn(args)
-
-       movi    a2, __NR_exit
-       syscall                         # return value of fn(args) still in a6
-
-1:     retw
-
-/*
- * Do a system call from kernel instead of calling sys_execve, so we end up
- * with proper pt_regs.
- *
- * int kernel_execve(const char *fname, char *const argv[], charg *const envp[])
- * a2                        a2               a3                  a4
- */
-
-ENTRY(kernel_execve)
-       entry   a1, 16
-       mov     a6, a2                  # arg0 is in a6
-       movi    a2, __NR_execve
-       syscall
-
-       retw
-
-/*
  * Task switch.
  *
  * struct task*  _switch_to (struct task* prev, struct task* next)
@@ -1901,8 +1857,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 +1866,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 +1880,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 +1893,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
 
@@ -1958,3 +1914,16 @@ ENTRY(ret_from_fork)
 
        j       common_exception_return
 
+/*
+ * Kernel thread creation helper
+ * On entry, set up by copy_thread: a2 = thread_fn, a3 = thread_fn arg
+ *           left from _switch_to: a6 = prev
+ */
+ENTRY(ret_from_kernel_thread)
+
+       call4   schedule_tail
+       mov     a6, a3
+       callx4  a2
+       j       common_exception_return
+
+ENDPROC(ret_from_kernel_thread)
index 3ef91a7..bdc5078 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 98e77c3..a6ce3e5 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 bc02082..09ae7bf 100644 (file)
@@ -45,6 +45,7 @@
 #include <asm/regs.h>
 
 extern void ret_from_fork(void);
+extern void ret_from_kernel_thread(void);
 
 struct task_struct *current_set[NR_CPUS] = {&init_task, };
 
@@ -158,64 +159,123 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 /*
  * Copy thread.
  *
+ * There are two modes in which this function is called:
+ * 1) Userspace thread creation,
+ *    regs != NULL, usp_thread_fn is userspace stack pointer.
+ *    It is expected to copy parent regs (in case CLONE_VM is not set
+ *    in the clone_flags) and set up passed usp in the childregs.
+ * 2) Kernel thread creation,
+ *    regs == NULL, usp_thread_fn is the function to run in the new thread
+ *    and thread_fn_arg is its parameter.
+ *    childregs are not used for the kernel threads.
+ *
  * The stack layout for the new thread looks like this:
  *
- *     +------------------------+ <- sp in childregs (= tos)
+ *     +------------------------+
  *     |       childregs        |
  *     +------------------------+ <- thread.sp = sp in dummy-frame
  *     |      dummy-frame       |    (saved in dummy-frame spill-area)
  *     +------------------------+
  *
- * We create a dummy frame to return to ret_from_fork:
- *   a0 points to ret_from_fork (simulating a call4)
+ * We create a dummy frame to return to either ret_from_fork or
+ *   ret_from_kernel_thread:
+ *   a0 points to ret_from_fork/ret_from_kernel_thread (simulating a call4)
  *   sp points to itself (thread.sp)
- *   a2, a3 are unused.
+ *   a2, a3 are unused for userspace threads,
+ *   a2 points to thread_fn, a3 holds thread_fn arg for kernel threads.
  *
  * 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,
-               unsigned long unused,
-                struct task_struct * p, struct pt_regs * regs)
+int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
+               unsigned long thread_fn_arg,
+               struct task_struct *p, struct pt_regs *unused)
 {
-       struct pt_regs *childregs;
-       struct thread_info *ti;
-       unsigned long tos;
-       int user_mode = user_mode(regs);
-
-       /* Set up new TSS. */
-       tos = (unsigned long)task_stack_page(p) + THREAD_SIZE;
-       if (user_mode)
-               childregs = (struct pt_regs*)(tos - PT_USER_SIZE);
-       else
-               childregs = (struct pt_regs*)tos - 1;
+       struct pt_regs *childregs = task_pt_regs(p);
 
-       *childregs = *regs;
+#if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS)
+       struct thread_info *ti;
+#endif
 
        /* 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);
        p->thread.sp = (unsigned long)childregs;
 
-       if (user_mode(regs)) {
+       if (!(p->flags & PF_KTHREAD)) {
+               struct pt_regs *regs = current_pt_regs();
+               unsigned long usp = usp_thread_fn ?
+                       usp_thread_fn : regs->areg[1];
 
-               int len = childregs->wmask & ~0xf;
+               p->thread.ra = MAKE_RA_FOR_CALL(
+                               (unsigned long)ret_from_fork, 0x1);
+
+               /* 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;
                childregs->areg[1] = usp;
-               memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4],
-                      &regs->areg[XCHAL_NUM_AREGS - len/4], len);
+               childregs->areg[2] = 0;
+
+               /* When sharing memory with the parent thread, the child
+                  usually starts on a pristine stack, so we have to reset
+                  windowbase, windowstart and wmask.
+                  (Note that such a new thread is required to always create
+                  an initial call4 frame)
+                  The exception is vfork, where the new thread continues to
+                  run on the parent's stack until it calls execve. This could
+                  be a call8 or call12, which requires a legal stack frame
+                  of the previous caller for the overflow handlers to work.
+                  (Note that it's always legal to overflow live registers).
+                  In this case, ensure to spill at least the stack pointer
+                  of that frame. */
+
+               if (clone_flags & CLONE_VM) {
+                       /* check that caller window is live and same stack */
+                       int len = childregs->wmask & ~0xf;
+                       if (regs->areg[1] == usp && len != 0) {
+                               int callinc = (regs->areg[0] >> 30) & 3;
+                               int caller_ars = XCHAL_NUM_AREGS - callinc * 4;
+                               put_user(regs->areg[caller_ars+1],
+                                        (unsigned __user*)(usp - 12));
+                       }
+                       childregs->wmask = 1;
+                       childregs->windowstart = 1;
+                       childregs->windowbase = 0;
+               } 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];
-
        } else {
-               /* In kernel space, we start a new thread with a new stack. */
-               childregs->wmask = 1;
+               p->thread.ra = MAKE_RA_FOR_CALL(
+                               (unsigned long)ret_from_kernel_thread, 1);
+
+               /* pass parameters to ret_from_kernel_thread:
+                * a2 = thread_fn, a3 = thread_fn arg
+                */
+               *((int *)childregs - 1) = thread_fn_arg;
+               *((int *)childregs - 2) = usp_thread_fn;
+
+               /* Childregs are only used when we're going to userspace
+                * in which case start_thread will set them up.
+                */
        }
 
 #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS)
@@ -311,32 +371,5 @@ long xtensa_clone(unsigned long clone_flags, unsigned long newsp,
                   void __user *child_tid, long a5,
                   struct pt_regs *regs)
 {
-        if (!newsp)
-                newsp = regs->areg[1];
         return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
 }
-
-/*
- * xtensa_execve() executes a new program.
- */
-
-asmlinkage
-long xtensa_execve(const char __user *name,
-                  const char __user *const __user *argv,
-                   const char __user *const __user *envp,
-                   long a3, long a4, long a5,
-                   struct pt_regs *regs)
-{
-       long error;
-       struct filename *filename;
-
-       filename = getname(name);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-       error = do_execve(filename->name, argv, envp, regs);
-       putname(filename);
-out:
-       return error;
-}
-
index 270360d..b237988 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 05b3f09..5702065 100644 (file)
@@ -32,11 +32,8 @@ typedef void (*syscall_t)(void);
 syscall_t sys_call_table[__NR_syscall_count] /* FIXME __cacheline_aligned */= {
        [0 ... __NR_syscall_count - 1] = (syscall_t)&sys_ni_syscall,
 
-#undef __SYSCALL
 #define __SYSCALL(nr,symbol,nargs) [ nr ] = (syscall_t)symbol,
-#undef _XTENSA_UNISTD_H
-#undef  __KERNEL_SYSCALLS__
-#include <asm/unistd.h>
+#include <uapi/asm/unistd.h>
 };
 
 asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)
@@ -50,7 +47,8 @@ asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)
        return (long)ret;
 }
 
-asmlinkage long xtensa_fadvise64_64(int fd, int advice, unsigned long long offset, unsigned long long len)
+asmlinkage long xtensa_fadvise64_64(int fd, int advice,
+               unsigned long long offset, unsigned long long len)
 {
        return sys_fadvise64_64(fd, offset, len, advice);
 }
index bc1e14c..5caf2b6 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 70066e3..4462c1e 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 a8b9f1f..afe058b 100644 (file)
@@ -43,7 +43,6 @@ EXPORT_SYMBOL(__strncpy_user);
 EXPORT_SYMBOL(clear_page);
 EXPORT_SYMBOL(copy_page);
 
-EXPORT_SYMBOL(kernel_thread);
 EXPORT_SYMBOL(empty_zero_page);
 
 /*
index ea59dcd..c48b80a 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 2c2f710..245b08f 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 8ab47ed..7e74895 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 8c43bfe..bd78192 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 927acf3..e170010 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 9e83940..c7d90f1 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 09acf1b..a7e40a7 100644 (file)
@@ -89,7 +89,7 @@ config BLK_DEV_INTEGRITY
 
 config BLK_DEV_THROTTLING
        bool "Block layer bio throttling support"
-       depends on BLK_CGROUP=y && EXPERIMENTAL
+       depends on BLK_CGROUP=y
        default n
        ---help---
        Block layer bio throttling support. It can be used to limit
index cafcd74..d0b7703 100644 (file)
@@ -285,6 +285,13 @@ static void blkg_destroy_all(struct request_queue *q)
                blkg_destroy(blkg);
                spin_unlock(&blkcg->lock);
        }
+
+       /*
+        * root blkg is destroyed.  Just clear the pointer since
+        * root_rl does not take reference on root blkg.
+        */
+       q->root_blkg = NULL;
+       q->root_rl.blkg = NULL;
 }
 
 static void blkg_rcu_free(struct rcu_head *rcu_head)
@@ -326,6 +333,9 @@ struct request_list *__blk_queue_next_rl(struct request_list *rl,
         */
        if (rl == &q->root_rl) {
                ent = &q->blkg_list;
+               /* There are no more block groups, hence no request lists */
+               if (list_empty(ent))
+                       return NULL;
        } else {
                blkg = container_of(rl, struct blkcg_gq, rl);
                ent = &blkg->q_node;
index a33870b..3c95c4d 100644 (file)
@@ -2868,7 +2868,8 @@ static int plug_rq_cmp(void *priv, struct list_head *a, struct list_head *b)
        struct request *rqa = container_of(a, struct request, queuelist);
        struct request *rqb = container_of(b, struct request, queuelist);
 
-       return !(rqa->q <= rqb->q);
+       return !(rqa->q < rqb->q ||
+               (rqa->q == rqb->q && blk_rq_pos(rqa) < blk_rq_pos(rqb)));
 }
 
 /*
index 8b6dc5b..f71eac3 100644 (file)
@@ -52,11 +52,17 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
                           rq_end_io_fn *done)
 {
        int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
+       bool is_pm_resume;
 
        WARN_ON(irqs_disabled());
 
        rq->rq_disk = bd_disk;
        rq->end_io = done;
+       /*
+        * need to check this before __blk_run_queue(), because rq can
+        * be freed before that returns.
+        */
+       is_pm_resume = rq->cmd_type == REQ_TYPE_PM_RESUME;
 
        spin_lock_irq(q->queue_lock);
 
@@ -71,7 +77,7 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
        __elv_add_request(q, rq, where);
        __blk_run_queue(q);
        /* the queue is stopped so it won't be run */
-       if (rq->cmd_type == REQ_TYPE_PM_RESUME)
+       if (is_pm_resume)
                q->request_fn(q);
        spin_unlock_irq(q->queue_lock);
 }
index 671d4d6..7bdd61b 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 03da5b6..a16a8d0 100644 (file)
@@ -17,6 +17,10 @@ obj-$(CONFIG_PARISC)         += parisc/
 obj-$(CONFIG_RAPIDIO)          += rapidio/
 obj-y                          += video/
 obj-y                          += idle/
+
+# IPMI must come before ACPI in order to provide IPMI opregion support
+obj-$(CONFIG_IPMI_HANDLER)     += char/ipmi/
+
 obj-$(CONFIG_ACPI)             += acpi/
 obj-$(CONFIG_SFI)              += sfi/
 # PnP must come after ACPI since it will eventually need to check if acpi
index 119d58d..0300bf6 100644 (file)
@@ -181,6 +181,12 @@ config ACPI_DOCK
          This driver supports ACPI-controlled docking stations and removable
          drive bays such as the IBM Ultrabay and the Dell Module Bay.
 
+config ACPI_I2C
+       def_tristate I2C
+       depends on I2C
+       help
+         ACPI I2C enumeration support.
+
 config ACPI_PROCESSOR
        tristate "Processor"
        select THERMAL
index 47199e2..2a4502b 100644 (file)
@@ -21,9 +21,10 @@ obj-y                                += acpi.o \
 acpi-y                         += osl.o utils.o reboot.o
 acpi-y                         += nvs.o
 
-# sleep related files
+# Power management related files
 acpi-y                         += wakeup.o
 acpi-y                         += sleep.o
+acpi-$(CONFIG_PM)              += device_pm.o
 acpi-$(CONFIG_ACPI_SLEEP)      += proc.o
 
 
@@ -32,10 +33,12 @@ acpi-$(CONFIG_ACPI_SLEEP)   += proc.o
 #
 acpi-y                         += bus.o glue.o
 acpi-y                         += scan.o
+acpi-y                         += resource.o
 acpi-y                         += processor_core.o
 acpi-y                         += ec.o
 acpi-$(CONFIG_ACPI_DOCK)       += dock.o
 acpi-y                         += pci_root.o pci_link.o pci_irq.o pci_bind.o
+acpi-y                         += acpi_platform.o
 acpi-y                         += power.o
 acpi-y                         += event.o
 acpi-y                         += sysfs.o
@@ -47,6 +50,10 @@ acpi-y                               += video_detect.o
 endif
 
 # These are (potentially) separate modules
+
+# IPMI may be used by other drivers, so it has to initialise before them
+obj-$(CONFIG_ACPI_IPMI)                += acpi_ipmi.o
+
 obj-$(CONFIG_ACPI_AC)          += ac.o
 obj-$(CONFIG_ACPI_BUTTON)      += button.o
 obj-$(CONFIG_ACPI_FAN)         += fan.o
@@ -63,6 +70,7 @@ obj-$(CONFIG_ACPI_HED)                += hed.o
 obj-$(CONFIG_ACPI_EC_DEBUGFS)  += ec_sys.o
 obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
 obj-$(CONFIG_ACPI_BGRT)                += bgrt.o
+obj-$(CONFIG_ACPI_I2C)         += acpi_i2c.o
 
 # processor has its own "processor." module_param namespace
 processor-y                    := processor_driver.o processor_throttling.o
@@ -70,6 +78,5 @@ processor-y                   += processor_idle.o processor_thermal.o
 processor-$(CONFIG_CPU_FREQ)   += processor_perflib.o
 
 obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o
-obj-$(CONFIG_ACPI_IPMI)                += acpi_ipmi.o
 
 obj-$(CONFIG_ACPI_APEI)                += apei/
diff --git a/drivers/acpi/acpi_i2c.c b/drivers/acpi/acpi_i2c.c
new file mode 100644 (file)
index 0000000..82045e3
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * ACPI I2C enumeration support
+ *
+ * Copyright (C) 2012, Intel Corporation
+ * Author: Mika Westerberg <mika.westerberg@linux.intel.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/acpi.h>
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/i2c.h>
+#include <linux/ioport.h>
+
+ACPI_MODULE_NAME("i2c");
+
+static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data)
+{
+       struct i2c_board_info *info = data;
+
+       if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
+               struct acpi_resource_i2c_serialbus *sb;
+
+               sb = &ares->data.i2c_serial_bus;
+               if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
+                       info->addr = sb->slave_address;
+                       if (sb->access_mode == ACPI_I2C_10BIT_MODE)
+                               info->flags |= I2C_CLIENT_TEN;
+               }
+       } else if (info->irq < 0) {
+               struct resource r;
+
+               if (acpi_dev_resource_interrupt(ares, 0, &r))
+                       info->irq = r.start;
+       }
+
+       /* Tell the ACPI core to skip this resource */
+       return 1;
+}
+
+static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
+                                      void *data, void **return_value)
+{
+       struct i2c_adapter *adapter = data;
+       struct list_head resource_list;
+       struct i2c_board_info info;
+       struct acpi_device *adev;
+       int ret;
+
+       if (acpi_bus_get_device(handle, &adev))
+               return AE_OK;
+       if (acpi_bus_get_status(adev) || !adev->status.present)
+               return AE_OK;
+
+       memset(&info, 0, sizeof(info));
+       info.acpi_node.handle = handle;
+       info.irq = -1;
+
+       INIT_LIST_HEAD(&resource_list);
+       ret = acpi_dev_get_resources(adev, &resource_list,
+                                    acpi_i2c_add_resource, &info);
+       acpi_dev_free_resource_list(&resource_list);
+
+       if (ret < 0 || !info.addr)
+               return AE_OK;
+
+       strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
+       if (!i2c_new_device(adapter, &info)) {
+               dev_err(&adapter->dev,
+                       "failed to add I2C device %s from ACPI\n",
+                       dev_name(&adev->dev));
+       }
+
+       return AE_OK;
+}
+
+/**
+ * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter
+ * @adapter: pointer to adapter
+ *
+ * Enumerate all I2C slave devices behind this adapter by walking the ACPI
+ * namespace. When a device is found it will be added to the Linux device
+ * model and bound to the corresponding ACPI handle.
+ */
+void acpi_i2c_register_devices(struct i2c_adapter *adapter)
+{
+       acpi_handle handle;
+       acpi_status status;
+
+       handle = ACPI_HANDLE(&adapter->dev);
+       if (!handle)
+               return;
+
+       status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
+                                    acpi_i2c_add_device, NULL,
+                                    adapter, NULL);
+       if (ACPI_FAILURE(status))
+               dev_warn(&adapter->dev, "failed to enumerate I2C slaves\n");
+}
+EXPORT_SYMBOL_GPL(acpi_i2c_register_devices);
index 24c807f..eb30e5a 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/types.h>
 #include <linux/memory_hotplug.h>
 #include <linux/slab.h>
+#include <linux/acpi.h>
 #include <acpi/acpi_drivers.h>
 
 #define ACPI_MEMORY_DEVICE_CLASS               "memory"
@@ -78,6 +79,7 @@ struct acpi_memory_info {
        unsigned short caching; /* memory cache attribute */
        unsigned short write_protect;   /* memory read/write attribute */
        unsigned int enabled:1;
+       unsigned int failed:1;
 };
 
 struct acpi_memory_device {
@@ -86,8 +88,6 @@ struct acpi_memory_device {
        struct list_head res_list;
 };
 
-static int acpi_hotmem_initialized;
-
 static acpi_status
 acpi_memory_get_resource(struct acpi_resource *resource, void *context)
 {
@@ -125,12 +125,20 @@ acpi_memory_get_resource(struct acpi_resource *resource, void *context)
        return AE_OK;
 }
 
+static void
+acpi_memory_free_device_resources(struct acpi_memory_device *mem_device)
+{
+       struct acpi_memory_info *info, *n;
+
+       list_for_each_entry_safe(info, n, &mem_device->res_list, list)
+               kfree(info);
+       INIT_LIST_HEAD(&mem_device->res_list);
+}
+
 static int
 acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
 {
        acpi_status status;
-       struct acpi_memory_info *info, *n;
-
 
        if (!list_empty(&mem_device->res_list))
                return 0;
@@ -138,9 +146,7 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
        status = acpi_walk_resources(mem_device->device->handle, METHOD_NAME__CRS,
                                     acpi_memory_get_resource, mem_device);
        if (ACPI_FAILURE(status)) {
-               list_for_each_entry_safe(info, n, &mem_device->res_list, list)
-                       kfree(info);
-               INIT_LIST_HEAD(&mem_device->res_list);
+               acpi_memory_free_device_resources(mem_device);
                return -EINVAL;
        }
 
@@ -170,7 +176,7 @@ acpi_memory_get_device(acpi_handle handle,
        /* Get the parent device */
        result = acpi_bus_get_device(phandle, &pdevice);
        if (result) {
-               printk(KERN_WARNING PREFIX "Cannot get acpi bus device");
+               acpi_handle_warn(phandle, "Cannot get acpi bus device\n");
                return -EINVAL;
        }
 
@@ -180,14 +186,14 @@ acpi_memory_get_device(acpi_handle handle,
         */
        result = acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE);
        if (result) {
-               printk(KERN_WARNING PREFIX "Cannot add acpi bus");
+               acpi_handle_warn(handle, "Cannot add acpi bus\n");
                return -EINVAL;
        }
 
       end:
        *mem_device = acpi_driver_data(device);
        if (!(*mem_device)) {
-               printk(KERN_ERR "\n driver data not found");
+               dev_err(&device->dev, "driver data not found\n");
                return -ENODEV;
        }
 
@@ -224,7 +230,8 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
        /* Get the range from the _CRS */
        result = acpi_memory_get_device_resources(mem_device);
        if (result) {
-               printk(KERN_ERR PREFIX "get_device_resources failed\n");
+               dev_err(&mem_device->device->dev,
+                       "get_device_resources failed\n");
                mem_device->state = MEMORY_INVALID_STATE;
                return result;
        }
@@ -251,13 +258,27 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
                        node = memory_add_physaddr_to_nid(info->start_addr);
 
                result = add_memory(node, info->start_addr, info->length);
-               if (result)
+
+               /*
+                * If the memory block has been used by the kernel, add_memory()
+                * returns -EEXIST. If add_memory() returns the other error, it
+                * means that this memory block is not used by the kernel.
+                */
+               if (result && result != -EEXIST) {
+                       info->failed = 1;
                        continue;
-               info->enabled = 1;
+               }
+
+               if (!result)
+                       info->enabled = 1;
+               /*
+                * Add num_enable even if add_memory() returns -EEXIST, so the
+                * device is bound to this driver.
+                */
                num_enabled++;
        }
        if (!num_enabled) {
-               printk(KERN_ERR PREFIX "add_memory failed\n");
+               dev_err(&mem_device->device->dev, "add_memory failed\n");
                mem_device->state = MEMORY_INVALID_STATE;
                return -EINVAL;
        }
@@ -272,68 +293,31 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
        return 0;
 }
 
-static int acpi_memory_powerdown_device(struct acpi_memory_device *mem_device)
+static int acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
 {
-       acpi_status status;
-       struct acpi_object_list arg_list;
-       union acpi_object arg;
-       unsigned long long current_status;
-
-
-       /* Issue the _EJ0 command */
-       arg_list.count = 1;
-       arg_list.pointer = &arg;
-       arg.type = ACPI_TYPE_INTEGER;
-       arg.integer.value = 1;
-       status = acpi_evaluate_object(mem_device->device->handle,
-                                     "_EJ0", &arg_list, NULL);
-       /* Return on _EJ0 failure */
-       if (ACPI_FAILURE(status)) {
-               ACPI_EXCEPTION((AE_INFO, status, "_EJ0 failed"));
-               return -ENODEV;
-       }
-
-       /* Evalute _STA to check if the device is disabled */
-       status = acpi_evaluate_integer(mem_device->device->handle, "_STA",
-                                      NULL, &current_status);
-       if (ACPI_FAILURE(status))
-               return -ENODEV;
-
-       /* Check for device status.  Device should be disabled */
-       if (current_status & ACPI_STA_DEVICE_ENABLED)
-               return -EINVAL;
+       int result = 0;
+       struct acpi_memory_info *info, *n;
 
-       return 0;
-}
+       list_for_each_entry_safe(info, n, &mem_device->res_list, list) {
+               if (info->failed)
+                       /* The kernel does not use this memory block */
+                       continue;
 
-static int acpi_memory_disable_device(struct acpi_memory_device *mem_device)
-{
-       int result;
-       struct acpi_memory_info *info, *n;
+               if (!info->enabled)
+                       /*
+                        * The kernel uses this memory block, but it may be not
+                        * managed by us.
+                        */
+                       return -EBUSY;
 
+               result = remove_memory(info->start_addr, info->length);
+               if (result)
+                       return result;
 
-       /*
-        * Ask the VM to offline this memory range.
-        * Note: Assume that this function returns zero on success
-        */
-       list_for_each_entry_safe(info, n, &mem_device->res_list, list) {
-               if (info->enabled) {
-                       result = remove_memory(info->start_addr, info->length);
-                       if (result)
-                               return result;
-               }
+               list_del(&info->list);
                kfree(info);
        }
 
-       /* Power-off and eject the device */
-       result = acpi_memory_powerdown_device(mem_device);
-       if (result) {
-               /* Set the status of the device to invalid */
-               mem_device->state = MEMORY_INVALID_STATE;
-               return result;
-       }
-
-       mem_device->state = MEMORY_POWER_OFF_STATE;
        return result;
 }
 
@@ -341,6 +325,7 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
 {
        struct acpi_memory_device *mem_device;
        struct acpi_device *device;
+       struct acpi_eject_event *ej_event = NULL;
        u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
 
        switch (event) {
@@ -353,7 +338,7 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
                        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                          "\nReceived DEVICE CHECK notification for device\n"));
                if (acpi_memory_get_device(handle, &mem_device)) {
-                       printk(KERN_ERR PREFIX "Cannot find driver data\n");
+                       acpi_handle_err(handle, "Cannot find driver data\n");
                        break;
                }
 
@@ -361,7 +346,7 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
                        break;
 
                if (acpi_memory_enable_device(mem_device)) {
-                       printk(KERN_ERR PREFIX "Cannot enable memory device\n");
+                       acpi_handle_err(handle,"Cannot enable memory device\n");
                        break;
                }
 
@@ -373,40 +358,28 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
                                  "\nReceived EJECT REQUEST notification for device\n"));
 
                if (acpi_bus_get_device(handle, &device)) {
-                       printk(KERN_ERR PREFIX "Device doesn't exist\n");
+                       acpi_handle_err(handle, "Device doesn't exist\n");
                        break;
                }
                mem_device = acpi_driver_data(device);
                if (!mem_device) {
-                       printk(KERN_ERR PREFIX "Driver Data is NULL\n");
+                       acpi_handle_err(handle, "Driver Data is NULL\n");
                        break;
                }
 
-               /*
-                * Currently disabling memory device from kernel mode
-                * TBD: Can also be disabled from user mode scripts
-                * TBD: Can also be disabled by Callback registration
-                *      with generic sysfs driver
-                */
-               if (acpi_memory_disable_device(mem_device)) {
-                       printk(KERN_ERR PREFIX "Disable memory device\n");
-                       /*
-                        * If _EJ0 was called but failed, _OST is not
-                        * necessary.
-                        */
-                       if (mem_device->state == MEMORY_INVALID_STATE)
-                               return;
-
+               ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
+               if (!ej_event) {
+                       pr_err(PREFIX "No memory, dropping EJECT\n");
                        break;
                }
 
-               /*
-                * TBD: Invoke acpi_bus_remove to cleanup data structures
-                */
+               ej_event->handle = handle;
+               ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
+               acpi_os_hotplug_execute(acpi_bus_hot_remove_device,
+                                       (void *)ej_event);
 
-               /* _EJ0 succeeded; _OST is not necessary */
+               /* eject is performed asynchronously */
                return;
-
        default:
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                  "Unsupported event [0x%x]\n", event));
@@ -420,6 +393,15 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data)
        return;
 }
 
+static void acpi_memory_device_free(struct acpi_memory_device *mem_device)
+{
+       if (!mem_device)
+               return;
+
+       acpi_memory_free_device_resources(mem_device);
+       kfree(mem_device);
+}
+
 static int acpi_memory_device_add(struct acpi_device *device)
 {
        int result;
@@ -449,23 +431,16 @@ static int acpi_memory_device_add(struct acpi_device *device)
        /* Set the device state */
        mem_device->state = MEMORY_POWER_ON_STATE;
 
-       printk(KERN_DEBUG "%s \n", acpi_device_name(device));
-
-       /*
-        * Early boot code has recognized memory area by EFI/E820.
-        * If DSDT shows these memory devices on boot, hotplug is not necessary
-        * for them. So, it just returns until completion of this driver's
-        * start up.
-        */
-       if (!acpi_hotmem_initialized)
-               return 0;
+       pr_debug("%s\n", acpi_device_name(device));
 
        if (!acpi_memory_check_device(mem_device)) {
                /* call add_memory func */
                result = acpi_memory_enable_device(mem_device);
-               if (result)
-                       printk(KERN_ERR PREFIX
+               if (result) {
+                       dev_err(&device->dev,
                                "Error in acpi_memory_enable_device\n");
+                       acpi_memory_device_free(mem_device);
+               }
        }
        return result;
 }
@@ -473,13 +448,18 @@ static int acpi_memory_device_add(struct acpi_device *device)
 static int acpi_memory_device_remove(struct acpi_device *device, int type)
 {
        struct acpi_memory_device *mem_device = NULL;
-
+       int result;
 
        if (!device || !acpi_driver_data(device))
                return -EINVAL;
 
        mem_device = acpi_driver_data(device);
-       kfree(mem_device);
+
+       result = acpi_memory_remove_memory(mem_device);
+       if (result)
+               return result;
+
+       acpi_memory_device_free(mem_device);
 
        return 0;
 }
@@ -568,7 +548,6 @@ static int __init acpi_memory_device_init(void)
                return -ENODEV;
        }
 
-       acpi_hotmem_initialized = 1;
        return 0;
 }
 
index af4aad6..16fa979 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;
        }
 }
diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c
new file mode 100644 (file)
index 0000000..db129b9
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * ACPI support for platform bus type.
+ *
+ * Copyright (C) 2012, Intel Corporation
+ * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
+ *          Mathias Nyman <mathias.nyman@linux.intel.com>
+ *          Rafael J. Wysocki <rafael.j.wysocki@intel.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/acpi.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include "internal.h"
+
+ACPI_MODULE_NAME("platform");
+
+/**
+ * acpi_create_platform_device - Create platform device for ACPI device node
+ * @adev: ACPI device node to create a platform device for.
+ *
+ * Check if the given @adev can be represented as a platform device and, if
+ * that's the case, create and register a platform device, populate its common
+ * resources and returns a pointer to it.  Otherwise, return %NULL.
+ *
+ * The platform device's name will be taken from the @adev's _HID and _UID.
+ */
+struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
+{
+       struct platform_device *pdev = NULL;
+       struct acpi_device *acpi_parent;
+       struct platform_device_info pdevinfo;
+       struct resource_list_entry *rentry;
+       struct list_head resource_list;
+       struct resource *resources;
+       int count;
+
+       /* If the ACPI node already has a physical device attached, skip it. */
+       if (adev->physical_node_count)
+               return NULL;
+
+       INIT_LIST_HEAD(&resource_list);
+       count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
+       if (count <= 0)
+               return NULL;
+
+       resources = kmalloc(count * sizeof(struct resource), GFP_KERNEL);
+       if (!resources) {
+               dev_err(&adev->dev, "No memory for resources\n");
+               acpi_dev_free_resource_list(&resource_list);
+               return NULL;
+       }
+       count = 0;
+       list_for_each_entry(rentry, &resource_list, node)
+               resources[count++] = rentry->res;
+
+       acpi_dev_free_resource_list(&resource_list);
+
+       memset(&pdevinfo, 0, sizeof(pdevinfo));
+       /*
+        * If the ACPI node has a parent and that parent has a physical device
+        * attached to it, that physical device should be the parent of the
+        * platform device we are about to create.
+        */
+       pdevinfo.parent = NULL;
+       acpi_parent = adev->parent;
+       if (acpi_parent) {
+               struct acpi_device_physical_node *entry;
+               struct list_head *list;
+
+               mutex_lock(&acpi_parent->physical_node_lock);
+               list = &acpi_parent->physical_node_list;
+               if (!list_empty(list)) {
+                       entry = list_first_entry(list,
+                                       struct acpi_device_physical_node,
+                                       node);
+                       pdevinfo.parent = entry->dev;
+               }
+               mutex_unlock(&acpi_parent->physical_node_lock);
+       }
+       pdevinfo.name = dev_name(&adev->dev);
+       pdevinfo.id = -1;
+       pdevinfo.res = resources;
+       pdevinfo.num_res = count;
+       pdevinfo.acpi_node.handle = adev->handle;
+       pdev = platform_device_register_full(&pdevinfo);
+       if (IS_ERR(pdev)) {
+               dev_err(&adev->dev, "platform device creation failed: %ld\n",
+                       PTR_ERR(pdev));
+               pdev = NULL;
+       } else {
+               dev_dbg(&adev->dev, "created platform device %s\n",
+                       dev_name(&pdev->dev));
+       }
+
+       kfree(resources);
+       return pdev;
+}
index 7f1d407..c8bc24b 100644 (file)
@@ -161,3 +161,6 @@ acpi-y +=           \
        utxfinit.o      \
        utxferror.o     \
        utxfmutex.o
+
+acpi-$(ACPI_FUTURE_USAGE) += uttrack.o utcache.o utclib.o
+
index 5e8abb0..432a318 100644 (file)
 #ifndef __ACDEBUG_H__
 #define __ACDEBUG_H__
 
-#define ACPI_DEBUG_BUFFER_SIZE  4196
+#define ACPI_DEBUG_BUFFER_SIZE  0x4000 /* 16K buffer for return objects */
 
-struct command_info {
+struct acpi_db_command_info {
        char *name;             /* Command Name */
        u8 min_args;            /* Minimum arguments required */
 };
 
-struct argument_info {
+struct acpi_db_command_help {
+       u8 line_count;          /* Number of help lines */
+       char *invocation;       /* Command Invocation */
+       char *description;      /* Command Description */
+};
+
+struct acpi_db_argument_info {
        char *name;             /* Argument Name */
 };
 
+struct acpi_db_execute_walk {
+       u32 count;
+       u32 max_count;
+};
+
 #define PARAM_LIST(pl)                  pl
 #define DBTEST_OUTPUT_LEVEL(lvl)        if (acpi_gbl_db_opt_verbose)
 #define VERBOSE_PRINT(fp)               DBTEST_OUTPUT_LEVEL(lvl) {\
@@ -77,59 +88,71 @@ acpi_db_single_step(struct acpi_walk_state *walk_state,
 /*
  * dbcmds - debug commands and output routines
  */
-acpi_status acpi_db_disassemble_method(char *name);
+struct acpi_namespace_node *acpi_db_convert_to_node(char *in_string);
 
 void acpi_db_display_table_info(char *table_arg);
 
-void acpi_db_unload_acpi_table(char *table_arg, char *instance_arg);
+void acpi_db_display_template(char *buffer_arg);
 
-void
-acpi_db_set_method_breakpoint(char *location,
-                             struct acpi_walk_state *walk_state,
-                             union acpi_parse_object *op);
+void acpi_db_unload_acpi_table(char *name);
 
-void acpi_db_set_method_call_breakpoint(union acpi_parse_object *op);
+void acpi_db_send_notify(char *name, u32 value);
 
-void acpi_db_get_bus_info(void);
+void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg);
 
-void acpi_db_disassemble_aml(char *statements, union acpi_parse_object *op);
+acpi_status acpi_db_sleep(char *object_arg);
 
-void acpi_db_dump_namespace(char *start_arg, char *depth_arg);
+void acpi_db_display_locks(void);
 
-void acpi_db_dump_namespace_by_owner(char *owner_arg, char *depth_arg);
+void acpi_db_display_resources(char *object_arg);
 
-void acpi_db_send_notify(char *name, u32 value);
+ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_display_gpes(void))
+
+void acpi_db_display_handlers(void);
+
+ACPI_HW_DEPENDENT_RETURN_VOID(void
+                             acpi_db_generate_gpe(char *gpe_arg,
+                                                  char *block_arg))
+
+/*
+ * dbmethod - control method commands
+ */
+void
+acpi_db_set_method_breakpoint(char *location,
+                             struct acpi_walk_state *walk_state,
+                             union acpi_parse_object *op);
+
+void acpi_db_set_method_call_breakpoint(union acpi_parse_object *op);
 
 void acpi_db_set_method_data(char *type_arg, char *index_arg, char *value_arg);
 
-acpi_status
-acpi_db_display_objects(char *obj_type_arg, char *display_count_arg);
+acpi_status acpi_db_disassemble_method(char *name);
 
-void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg);
+void acpi_db_disassemble_aml(char *statements, union acpi_parse_object *op);
 
-acpi_status acpi_db_find_name_in_namespace(char *name_arg);
+void acpi_db_batch_execute(char *count_arg);
 
+/*
+ * dbnames - namespace commands
+ */
 void acpi_db_set_scope(char *name);
 
-ACPI_HW_DEPENDENT_RETURN_OK(acpi_status acpi_db_sleep(char *object_arg))
+void acpi_db_dump_namespace(char *start_arg, char *depth_arg);
 
-void acpi_db_find_references(char *object_arg);
+void acpi_db_dump_namespace_by_owner(char *owner_arg, char *depth_arg);
 
-void acpi_db_display_locks(void);
+acpi_status acpi_db_find_name_in_namespace(char *name_arg);
 
-void acpi_db_display_resources(char *object_arg);
+void acpi_db_check_predefined_names(void);
 
-ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_display_gpes(void))
+acpi_status
+acpi_db_display_objects(char *obj_type_arg, char *display_count_arg);
 
 void acpi_db_check_integrity(void);
 
-ACPI_HW_DEPENDENT_RETURN_VOID(void
-                             acpi_db_generate_gpe(char *gpe_arg,
-                                                  char *block_arg))
-
-void acpi_db_check_predefined_names(void);
+void acpi_db_find_references(char *object_arg);
 
-void acpi_db_batch_execute(void);
+void acpi_db_get_bus_info(void);
 
 /*
  * dbdisply - debug display commands
@@ -161,7 +184,8 @@ acpi_db_display_argument_object(union acpi_operand_object *obj_desc,
 /*
  * dbexec - debugger control method execution
  */
-void acpi_db_execute(char *name, char **args, u32 flags);
+void
+acpi_db_execute(char *name, char **args, acpi_object_type * types, u32 flags);
 
 void
 acpi_db_create_execution_threads(char *num_threads_arg,
@@ -175,7 +199,8 @@ u32 acpi_db_get_cache_info(struct acpi_memory_list *cache);
  * dbfileio - Debugger file I/O commands
  */
 acpi_object_type
-acpi_db_match_argument(char *user_argument, struct argument_info *arguments);
+acpi_db_match_argument(char *user_argument,
+                      struct acpi_db_argument_info *arguments);
 
 void acpi_db_close_debug_file(void);
 
@@ -208,6 +233,11 @@ acpi_db_command_dispatch(char *input_buffer,
 
 void ACPI_SYSTEM_XFACE acpi_db_execute_thread(void *context);
 
+acpi_status acpi_db_user_commands(char prompt, union acpi_parse_object *op);
+
+char *acpi_db_get_next_token(char *string,
+                            char **next, acpi_object_type * return_type);
+
 /*
  * dbstats - Generation and display of ACPI table statistics
  */
index 5935ba6..ed33ebc 100644 (file)
@@ -309,10 +309,13 @@ acpi_ds_obj_stack_push(void *object, struct acpi_walk_state *walk_state);
 acpi_status
 acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state *walk_state);
 
-struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union acpi_parse_object
-                                                 *origin, union acpi_operand_object
-                                                 *mth_desc, struct acpi_thread_state
-                                                 *thread);
+struct acpi_walk_state * acpi_ds_create_walk_state(acpi_owner_id owner_id,
+                                                  union acpi_parse_object
+                                                  *origin,
+                                                  union acpi_operand_object
+                                                  *mth_desc,
+                                                  struct acpi_thread_state
+                                                  *thread);
 
 acpi_status
 acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state,
index c0a43b3..e975c67 100644 (file)
@@ -84,9 +84,11 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info);
 
 acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info);
 
-acpi_status acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info);
+acpi_status
+acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info);
 
-acpi_status acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info);
+acpi_status
+acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info);
 
 struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
                                                       u32 gpe_number);
index ce79100..64472e4 100644 (file)
@@ -70,7 +70,7 @@
 
 /*
  * Enable "slack" in the AML interpreter?  Default is FALSE, and the
- * interpreter strictly follows the ACPI specification.  Setting to TRUE
+ * interpreter strictly follows the ACPI specification. Setting to TRUE
  * allows the interpreter to ignore certain errors and/or bad AML constructs.
  *
  * Currently, these features are enabled by this flag:
@@ -155,26 +155,6 @@ ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_no_resource_disassembly, FALSE);
 
 /*****************************************************************************
  *
- * Debug support
- *
- ****************************************************************************/
-
-/* Procedure nesting level for debug output */
-
-extern u32 acpi_gbl_nesting_level;
-
-ACPI_EXTERN u32 acpi_gpe_count;
-ACPI_EXTERN u32 acpi_fixed_event_count[ACPI_NUM_FIXED_EVENTS];
-
-/* Support for dynamic control method tracing mechanism */
-
-ACPI_EXTERN u32 acpi_gbl_original_dbg_level;
-ACPI_EXTERN u32 acpi_gbl_original_dbg_layer;
-ACPI_EXTERN u32 acpi_gbl_trace_dbg_level;
-ACPI_EXTERN u32 acpi_gbl_trace_dbg_layer;
-
-/*****************************************************************************
- *
  * ACPI Table globals
  *
  ****************************************************************************/
@@ -259,15 +239,6 @@ ACPI_EXTERN acpi_spinlock acpi_gbl_hardware_lock;  /* For ACPI H/W except GPE reg
  *
  ****************************************************************************/
 
-#ifdef ACPI_DBG_TRACK_ALLOCATIONS
-
-/* Lists for tracking memory allocations */
-
-ACPI_EXTERN struct acpi_memory_list *acpi_gbl_global_list;
-ACPI_EXTERN struct acpi_memory_list *acpi_gbl_ns_node_list;
-ACPI_EXTERN u8 acpi_gbl_display_final_mem_stats;
-#endif
-
 /* Object caches */
 
 ACPI_EXTERN acpi_cache_t *acpi_gbl_namespace_cache;
@@ -326,6 +297,15 @@ extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS];
 
 #endif
 
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+
+/* Lists for tracking memory allocations */
+
+ACPI_EXTERN struct acpi_memory_list *acpi_gbl_global_list;
+ACPI_EXTERN struct acpi_memory_list *acpi_gbl_ns_node_list;
+ACPI_EXTERN u8 acpi_gbl_display_final_mem_stats;
+#endif
+
 /*****************************************************************************
  *
  * Namespace globals
@@ -396,13 +376,35 @@ ACPI_EXTERN struct acpi_gpe_block_info
 #if (!ACPI_REDUCED_HARDWARE)
 
 ACPI_EXTERN u8 acpi_gbl_all_gpes_initialized;
-ACPI_EXTERN ACPI_GBL_EVENT_HANDLER acpi_gbl_global_event_handler;
+ACPI_EXTERN acpi_gbl_event_handler acpi_gbl_global_event_handler;
 ACPI_EXTERN void *acpi_gbl_global_event_handler_context;
 
 #endif                         /* !ACPI_REDUCED_HARDWARE */
 
 /*****************************************************************************
  *
+ * Debug support
+ *
+ ****************************************************************************/
+
+/* Procedure nesting level for debug output */
+
+extern u32 acpi_gbl_nesting_level;
+
+/* Event counters */
+
+ACPI_EXTERN u32 acpi_gpe_count;
+ACPI_EXTERN u32 acpi_fixed_event_count[ACPI_NUM_FIXED_EVENTS];
+
+/* Support for dynamic control method tracing mechanism */
+
+ACPI_EXTERN u32 acpi_gbl_original_dbg_level;
+ACPI_EXTERN u32 acpi_gbl_original_dbg_layer;
+ACPI_EXTERN u32 acpi_gbl_trace_dbg_level;
+ACPI_EXTERN u32 acpi_gbl_trace_dbg_layer;
+
+/*****************************************************************************
+ *
  * Debugger globals
  *
  ****************************************************************************/
@@ -426,10 +428,11 @@ ACPI_EXTERN u8 acpi_gbl_db_opt_stats;
 ACPI_EXTERN u8 acpi_gbl_db_opt_ini_methods;
 
 ACPI_EXTERN char *acpi_gbl_db_args[ACPI_DEBUGGER_MAX_ARGS];
-ACPI_EXTERN char acpi_gbl_db_line_buf[80];
-ACPI_EXTERN char acpi_gbl_db_parsed_buf[80];
-ACPI_EXTERN char acpi_gbl_db_scope_buf[40];
-ACPI_EXTERN char acpi_gbl_db_debug_filename[40];
+ACPI_EXTERN acpi_object_type acpi_gbl_db_arg_types[ACPI_DEBUGGER_MAX_ARGS];
+ACPI_EXTERN char acpi_gbl_db_line_buf[ACPI_DB_LINE_BUFFER_SIZE];
+ACPI_EXTERN char acpi_gbl_db_parsed_buf[ACPI_DB_LINE_BUFFER_SIZE];
+ACPI_EXTERN char acpi_gbl_db_scope_buf[80];
+ACPI_EXTERN char acpi_gbl_db_debug_filename[80];
 ACPI_EXTERN u8 acpi_gbl_db_output_to_file;
 ACPI_EXTERN char *acpi_gbl_db_buffer;
 ACPI_EXTERN char *acpi_gbl_db_filename;
index c816ee6..ff8bd00 100644 (file)
@@ -262,10 +262,10 @@ struct acpi_create_field_info {
 };
 
 typedef
-acpi_status(*ACPI_INTERNAL_METHOD) (struct acpi_walk_state * walk_state);
+acpi_status(*acpi_internal_method) (struct acpi_walk_state * walk_state);
 
 /*
- * Bitmapped ACPI types.  Used internally only
+ * Bitmapped ACPI types. Used internally only
  */
 #define ACPI_BTYPE_ANY                  0x00000000
 #define ACPI_BTYPE_INTEGER              0x00000001
@@ -486,8 +486,10 @@ struct acpi_gpe_device_info {
        struct acpi_namespace_node *gpe_device;
 };
 
-typedef acpi_status(*acpi_gpe_callback) (struct acpi_gpe_xrupt_info *gpe_xrupt_info,
-               struct acpi_gpe_block_info *gpe_block, void *context);
+typedef acpi_status(*acpi_gpe_callback) (struct acpi_gpe_xrupt_info *
+                                        gpe_xrupt_info,
+                                        struct acpi_gpe_block_info *gpe_block,
+                                        void *context);
 
 /* Information about each particular fixed event */
 
@@ -582,7 +584,7 @@ struct acpi_pscope_state {
 };
 
 /*
- * Thread state - one per thread across multiple walk states.  Multiple walk
+ * Thread state - one per thread across multiple walk states. Multiple walk
  * states are created when there are nested control methods executing.
  */
 struct acpi_thread_state {
@@ -645,7 +647,7 @@ union acpi_generic_state {
  *
  ****************************************************************************/
 
-typedef acpi_status(*ACPI_EXECUTE_OP) (struct acpi_walk_state * walk_state);
+typedef acpi_status(*acpi_execute_op) (struct acpi_walk_state * walk_state);
 
 /* Address Range info block */
 
@@ -1031,6 +1033,7 @@ struct acpi_db_method_info {
        acpi_handle method;
        acpi_handle main_thread_gate;
        acpi_handle thread_complete_gate;
+       acpi_handle info_gate;
        acpi_thread_id *threads;
        u32 num_threads;
        u32 num_created;
@@ -1041,6 +1044,7 @@ struct acpi_db_method_info {
        u32 num_loops;
        char pathname[128];
        char **args;
+       acpi_object_type *types;
 
        /*
         * Arguments to be passed to method for the command
index a7f68c4..5efad99 100644 (file)
 
 /* These macros reverse the bytes during the move, converting little-endian to big endian */
 
-                         /* Big Endian      <==        Little Endian */
-                         /*  Hi...Lo                     Lo...Hi     */
+        /* Big Endian      <==        Little Endian */
+        /*  Hi...Lo                     Lo...Hi     */
 /* 16-bit source, 16/32/64 destination */
 
 #define ACPI_MOVE_16_TO_16(d, s)        {((  u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[1];\
-                                          ((  u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[0];}
+                         ((  u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[0];}
 
 #define ACPI_MOVE_16_TO_32(d, s)        {(*(u32 *)(void *)(d))=0;\
-                                                          ((u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\
-                                                          ((u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];}
+                                         ((u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\
+                                         ((u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];}
 
 #define ACPI_MOVE_16_TO_64(d, s)        {(*(u64 *)(void *)(d))=0;\
-                                                                        ((u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[1];\
-                                                                        ((u8 *)(void *)(d))[7] = ((u8 *)(void *)(s))[0];}
+                                                          ((u8 *)(void *)(d))[6] = ((u8 *)(void *)(s))[1];\
+                                                          ((u8 *)(void *)(d))[7] = ((u8 *)(void *)(s))[0];}
 
 /* 32-bit source, 16/32/64 destination */
 
 #define ACPI_MOVE_32_TO_16(d, s)        ACPI_MOVE_16_TO_16(d, s)       /* Truncate to 16 */
 
 #define ACPI_MOVE_32_TO_32(d, s)        {((  u8 *)(void *)(d))[0] = ((u8 *)(void *)(s))[3];\
-                                                                                ((  u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[2];\
-                                                                                ((  u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\
-                                                                                ((  u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];}
+                                                                         ((  u8 *)(void *)(d))[1] = ((u8 *)(void *)(s))[2];\
+                                                                         ((  u8 *)(void *)(d))[2] = ((u8 *)(void *)(s))[1];\
+                                                                         ((  u8 *)(void *)(d))[3] = ((u8 *)(void *)(s))[0];}
 
 #define ACPI_MOVE_32_TO_64(d, s)        {(*(u64 *)(void *)(d))=0;\
                                                                                   ((u8 *)(void *)(d))[4] = ((u8 *)(void *)(s))[3];\
 #endif
 #endif
 
-/* Macros based on machine integer width */
-
-#if ACPI_MACHINE_WIDTH == 32
-#define ACPI_MOVE_SIZE_TO_16(d, s)       ACPI_MOVE_32_TO_16(d, s)
-
-#elif ACPI_MACHINE_WIDTH == 64
-#define ACPI_MOVE_SIZE_TO_16(d, s)       ACPI_MOVE_64_TO_16(d, s)
-
-#else
-#error unknown ACPI_MACHINE_WIDTH
-#endif
-
 /*
  * Fast power-of-two math macros for non-optimized compilers
  */
-#define _ACPI_DIV(value, power_of2)      ((u32) ((value) >> (power_of2)))
-#define _ACPI_MUL(value, power_of2)      ((u32) ((value) << (power_of2)))
-#define _ACPI_MOD(value, divisor)        ((u32) ((value) & ((divisor) -1)))
+#define _ACPI_DIV(value, power_of2)     ((u32) ((value) >> (power_of2)))
+#define _ACPI_MUL(value, power_of2)     ((u32) ((value) << (power_of2)))
+#define _ACPI_MOD(value, divisor)       ((u32) ((value) & ((divisor) -1)))
 
 #define ACPI_DIV_2(a)                   _ACPI_DIV(a, 1)
 #define ACPI_MUL_2(a)                   _ACPI_MUL(a, 1)
 /*
  * Rounding macros (Power of two boundaries only)
  */
-#define ACPI_ROUND_DOWN(value, boundary)     (((acpi_size)(value)) & \
-                                               (~(((acpi_size) boundary)-1)))
+#define ACPI_ROUND_DOWN(value, boundary)    (((acpi_size)(value)) & \
+                                                                                               (~(((acpi_size) boundary)-1)))
 
-#define ACPI_ROUND_UP(value, boundary)      ((((acpi_size)(value)) + \
-                                               (((acpi_size) boundary)-1)) & \
-                                               (~(((acpi_size) boundary)-1)))
+#define ACPI_ROUND_UP(value, boundary)      ((((acpi_size)(value)) + \
+                                                                                               (((acpi_size) boundary)-1)) & \
+                                                                                               (~(((acpi_size) boundary)-1)))
 
 /* Note: sizeof(acpi_size) evaluates to either 4 or 8 (32- vs 64-bit mode) */
 
 
 #define ACPI_ROUND_UP_TO(value, boundary)   (((value) + ((boundary)-1)) / (boundary))
 
-#define ACPI_IS_MISALIGNED(value)          (((acpi_size) value) & (sizeof(acpi_size)-1))
+#define ACPI_IS_MISALIGNED(value)           (((acpi_size) value) & (sizeof(acpi_size)-1))
 
 /*
  * Bitmask creation
  * Ascii error messages can be configured out
  */
 #ifndef ACPI_NO_ERROR_MESSAGES
-
 /*
  * Error reporting. Callers module and line number are inserted by AE_INFO,
  * the plist contains a set of parens to allow variable-length lists.
 #define ACPI_WARN_PREDEFINED(plist)
 #define ACPI_INFO_PREDEFINED(plist)
 
-#endif         /* ACPI_NO_ERROR_MESSAGES */
+#endif                         /* ACPI_NO_ERROR_MESSAGES */
 
 /*
  * Debug macros that are conditionally compiled
  */
 #ifdef ACPI_DEBUG_OUTPUT
-
 /*
  * Function entry tracing
  */
-#ifdef CONFIG_ACPI_DEBUG_FUNC_TRACE
-
 #define ACPI_FUNCTION_TRACE(a)          ACPI_FUNCTION_NAME(a) \
                          acpi_ut_trace(ACPI_DEBUG_PARAMETERS)
 #define ACPI_FUNCTION_TRACE_PTR(a, b)   ACPI_FUNCTION_NAME(a) \
 
 #endif                         /* ACPI_SIMPLE_RETURN_MACROS */
 
-#else /* !CONFIG_ACPI_DEBUG_FUNC_TRACE */
-
-#define ACPI_FUNCTION_TRACE(a)
-#define ACPI_FUNCTION_TRACE_PTR(a,b)
-#define ACPI_FUNCTION_TRACE_U32(a,b)
-#define ACPI_FUNCTION_TRACE_STR(a,b)
-#define ACPI_FUNCTION_EXIT
-#define ACPI_FUNCTION_STATUS_EXIT(s)
-#define ACPI_FUNCTION_VALUE_EXIT(s)
-#define ACPI_FUNCTION_TRACE(a)
-#define ACPI_FUNCTION_ENTRY()
-
-#define return_VOID                     return
-#define return_ACPI_STATUS(s)           return(s)
-#define return_VALUE(s)                 return(s)
-#define return_UINT8(s)                 return(s)
-#define return_UINT32(s)                return(s)
-#define return_PTR(s)                   return(s)
-
-#endif /* CONFIG_ACPI_DEBUG_FUNC_TRACE */
-
 /* Conditional execution */
 
 #define ACPI_DEBUG_EXEC(a)              a
-#define ACPI_NORMAL_EXEC(a)
-
-#define ACPI_DEBUG_DEFINE(a)            a;
 #define ACPI_DEBUG_ONLY_MEMBERS(a)      a;
 #define _VERBOSE_STRUCTURES
 
-/* Stack and buffer dumping */
+/* Various object display routines for debug */
 
 #define ACPI_DUMP_STACK_ENTRY(a)        acpi_ex_dump_operand((a), 0)
-#define ACPI_DUMP_OPERANDS(a, b, c)    acpi_ex_dump_operands(a, b, c)
-
+#define ACPI_DUMP_OPERANDS(a, b ,c)     acpi_ex_dump_operands(a, b, c)
 #define ACPI_DUMP_ENTRY(a, b)           acpi_ns_dump_entry (a, b)
 #define ACPI_DUMP_PATHNAME(a, b, c, d)  acpi_ns_dump_pathname(a, b, c, d)
-#define ACPI_DUMP_RESOURCE_LIST(a)      acpi_rs_dump_resource_list(a)
-#define ACPI_DUMP_BUFFER(a, b)          acpi_ut_dump_buffer((u8 *) a, b, DB_BYTE_DISPLAY, _COMPONENT)
+#define ACPI_DUMP_BUFFER(a, b)          acpi_ut_debug_dump_buffer((u8 *) a, b, DB_BYTE_DISPLAY, _COMPONENT)
 
 #else
 /*
  * leaving no executable debug code!
  */
 #define ACPI_DEBUG_EXEC(a)
-#define ACPI_NORMAL_EXEC(a)             a;
-
-#define ACPI_DEBUG_DEFINE(a)           do { } while(0)
-#define ACPI_DEBUG_ONLY_MEMBERS(a)     do { } while(0)
-#define ACPI_FUNCTION_TRACE(a)         do { } while(0)
-#define ACPI_FUNCTION_TRACE_PTR(a, b)  do { } while(0)
-#define ACPI_FUNCTION_TRACE_U32(a, b)  do { } while(0)
-#define ACPI_FUNCTION_TRACE_STR(a, b)  do { } while(0)
-#define ACPI_FUNCTION_EXIT             do { } while(0)
-#define ACPI_FUNCTION_STATUS_EXIT(s)   do { } while(0)
-#define ACPI_FUNCTION_VALUE_EXIT(s)    do { } while(0)
-#define ACPI_FUNCTION_ENTRY()          do { } while(0)
-#define ACPI_DUMP_STACK_ENTRY(a)       do { } while(0)
-#define ACPI_DUMP_OPERANDS(a, b, c)     do { } while(0)
-#define ACPI_DUMP_ENTRY(a, b)          do { } while(0)
-#define ACPI_DUMP_TABLES(a, b)         do { } while(0)
-#define ACPI_DUMP_PATHNAME(a, b, c, d) do { } while(0)
-#define ACPI_DUMP_RESOURCE_LIST(a)     do { } while(0)
-#define ACPI_DUMP_BUFFER(a, b)         do { } while(0)
+#define ACPI_DEBUG_ONLY_MEMBERS(a)
+#define ACPI_FUNCTION_TRACE(a)
+#define ACPI_FUNCTION_TRACE_PTR(a, b)
+#define ACPI_FUNCTION_TRACE_U32(a, b)
+#define ACPI_FUNCTION_TRACE_STR(a, b)
+#define ACPI_FUNCTION_EXIT
+#define ACPI_FUNCTION_STATUS_EXIT(s)
+#define ACPI_FUNCTION_VALUE_EXIT(s)
+#define ACPI_FUNCTION_ENTRY()
+#define ACPI_DUMP_STACK_ENTRY(a)
+#define ACPI_DUMP_OPERANDS(a, b, c)
+#define ACPI_DUMP_ENTRY(a, b)
+#define ACPI_DUMP_TABLES(a, b)
+#define ACPI_DUMP_PATHNAME(a, b, c, d)
+#define ACPI_DUMP_BUFFER(a, b)
+#define ACPI_DEBUG_PRINT(pl)
+#define ACPI_DEBUG_PRINT_RAW(pl)
 
 #define return_VOID                     return
 #define return_ACPI_STATUS(s)           return(s)
 #define ACPI_DEBUGGER_EXEC(a)
 #endif
 
-#ifdef ACPI_DEBUG_OUTPUT
-/*
- * 1) Set name to blanks
- * 2) Copy the object name
- */
-#define ACPI_ADD_OBJECT_NAME(a,b)       ACPI_MEMSET (a->common.name, ' ', sizeof (a->common.name));\
-                                                                               ACPI_STRNCPY (a->common.name, acpi_gbl_ns_type_names[b], sizeof (a->common.name))
-#else
-
-#define ACPI_ADD_OBJECT_NAME(a,b)
-#endif
-
 /*
  * Memory allocation tracking (DEBUG ONLY)
  */
 /* Memory allocation */
 
 #ifndef ACPI_ALLOCATE
-#define ACPI_ALLOCATE(a)            acpi_ut_allocate((acpi_size)(a), ACPI_MEM_PARAMETERS)
+#define ACPI_ALLOCATE(a)            acpi_ut_allocate((acpi_size) (a), ACPI_MEM_PARAMETERS)
 #endif
 #ifndef ACPI_ALLOCATE_ZEROED
-#define ACPI_ALLOCATE_ZEROED(a)     acpi_ut_allocate_zeroed((acpi_size)(a), ACPI_MEM_PARAMETERS)
+#define ACPI_ALLOCATE_ZEROED(a)     acpi_ut_allocate_zeroed((acpi_size) (a), ACPI_MEM_PARAMETERS)
 #endif
 #ifndef ACPI_FREE
-#define ACPI_FREE(a)                acpio_os_free(a)
+#define ACPI_FREE(a)                acpi_os_free(a)
 #endif
 #define ACPI_MEM_TRACKING(a)
 
 
 /* Memory allocation */
 
-#define ACPI_ALLOCATE(a)            acpi_ut_allocate_and_track((acpi_size)(a), ACPI_MEM_PARAMETERS)
-#define ACPI_ALLOCATE_ZEROED(a)     acpi_ut_allocate_zeroed_and_track((acpi_size)(a), ACPI_MEM_PARAMETERS)
+#define ACPI_ALLOCATE(a)            acpi_ut_allocate_and_track((acpi_size) (a), ACPI_MEM_PARAMETERS)
+#define ACPI_ALLOCATE_ZEROED(a)     acpi_ut_allocate_zeroed_and_track((acpi_size) (a), ACPI_MEM_PARAMETERS)
 #define ACPI_FREE(a)                acpi_ut_free_and_track(a, ACPI_MEM_PARAMETERS)
 #define ACPI_MEM_TRACKING(a)        a
 
 #endif                         /* ACPI_DBG_TRACK_ALLOCATIONS */
 
-/* Preemption point */
-#ifndef ACPI_PREEMPTION_POINT
-#define ACPI_PREEMPTION_POINT() /* no preemption */
-#endif
+/*
+ * Macros used for ACPICA utilities only
+ */
+
+/* Generate a UUID */
+
+#define ACPI_INIT_UUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \
+       (a) & 0xFF, ((a) >> 8) & 0xFF, ((a) >> 16) & 0xFF, ((a) >> 24) & 0xFF, \
+       (b) & 0xFF, ((b) >> 8) & 0xFF, \
+       (c) & 0xFF, ((c) >> 8) & 0xFF, \
+       (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7)
+
+#define ACPI_IS_OCTAL_DIGIT(d)              (((char)(d) >= '0') && ((char)(d) <= '7'))
 
 #endif                         /* ACMACROS_H */
index 364a130..24eb9ea 100644 (file)
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Name: acobject.h - Definition of union acpi_operand_object  (Internal object only)
@@ -179,7 +178,7 @@ struct acpi_object_method {
        union acpi_operand_object *mutex;
        u8 *aml_start;
        union {
-               ACPI_INTERNAL_METHOD implementation;
+               acpi_internal_method implementation;
                union acpi_operand_object *handler;
        } dispatch;
 
@@ -198,7 +197,7 @@ struct acpi_object_method {
 
 /******************************************************************************
  *
- * Objects that can be notified.  All share a common notify_info area.
+ * Objects that can be notified. All share a common notify_info area.
  *
  *****************************************************************************/
 
@@ -235,7 +234,7 @@ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO};
 
 /******************************************************************************
  *
- * Fields.  All share a common header/info field.
+ * Fields. All share a common header/info field.
  *
  *****************************************************************************/
 
index 9440d05..d786a51 100644 (file)
@@ -54,7 +54,7 @@
 #define _UNK                        0x6B
 
 /*
- * Reserved ASCII characters.  Do not use any of these for
+ * Reserved ASCII characters. Do not use any of these for
  * internal opcodes, since they are used to differentiate
  * name strings from AML opcodes
  */
@@ -63,7 +63,7 @@
 #define _PFX                        0x6D
 
 /*
- * All AML opcodes and the parse-time arguments for each.  Used by the AML
+ * All AML opcodes and the parse-time arguments for each. Used by the AML
  * parser  Each list is compressed into a 32-bit number and stored in the
  * master opcode table (in psopcode.c).
  */
 #define ARGP_ZERO_OP                    ARG_NONE
 
 /*
- * All AML opcodes and the runtime arguments for each.  Used by the AML
+ * All AML opcodes and the runtime arguments for each. Used by the AML
  * interpreter  Each list is compressed into a 32-bit number and stored
  * in the master opcode table (in psopcode.c).
  *
index b725d78..eefcf47 100644 (file)
@@ -150,8 +150,7 @@ u8 acpi_ps_has_completed_scope(struct acpi_parse_state *parser_state);
 
 void
 acpi_ps_pop_scope(struct acpi_parse_state *parser_state,
-                 union acpi_parse_object **op,
-                 u32 * arg_list, u32 * arg_count);
+                 union acpi_parse_object **op, u32 *arg_list, u32 *arg_count);
 
 acpi_status
 acpi_ps_push_scope(struct acpi_parse_state *parser_state,
index 3080c01..9dfa1c8 100644 (file)
@@ -150,8 +150,7 @@ enum acpi_return_package_types {
  * is saved here (rather than in a separate table) in order to minimize the
  * overall size of the stored data.
  */
-static const union acpi_predefined_info predefined_names[] =
-{
+static const union acpi_predefined_info predefined_names[] = {
        {{"_AC0", 0, ACPI_RTYPE_INTEGER}},
        {{"_AC1", 0, ACPI_RTYPE_INTEGER}},
        {{"_AC2", 0, ACPI_RTYPE_INTEGER}},
@@ -538,7 +537,8 @@ static const union acpi_predefined_info predefined_names[] =
 
        /* Acpi 1.0 defined _WAK with no return value. Later, it was changed to return a package */
 
-       {{"_WAK", 1, ACPI_RTYPE_NONE | ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE}},
+       {{"_WAK", 1,
+          ACPI_RTYPE_NONE | ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE}},
                          {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 2,0}, 0,0}}, /* Fixed-length (2 Int), but is optional */
 
        /* _WDG/_WED are MS extensions defined by "Windows Instrumentation" */
@@ -551,11 +551,12 @@ static const union acpi_predefined_info predefined_names[] =
 };
 
 #if 0
+
        /* This is an internally implemented control method, no need to check */
-       {{"_OSI", 1, ACPI_RTYPE_INTEGER}},
+{ {
+"_OSI", 1, ACPI_RTYPE_INTEGER}},
 
        /* TBD: */
-
        _PRT - currently ignore reversed entries. attempt to fix here?
        think about possibly fixing package elements like _BIF, etc.
 #endif
index f196e2c..937e66c 100644 (file)
@@ -53,7 +53,7 @@
  ****************************************************************************/
 
 /*
- * Walk state - current state of a parse tree walk.  Used for both a leisurely
+ * Walk state - current state of a parse tree walk. Used for both a leisurely
  * stroll through the tree (for whatever reason), and for control method
  * execution.
  */
index 5035327..b0f5f92 100644 (file)
@@ -69,6 +69,22 @@ extern const char *acpi_gbl_siz_decode[];
 extern const char *acpi_gbl_trs_decode[];
 extern const char *acpi_gbl_ttp_decode[];
 extern const char *acpi_gbl_typ_decode[];
+extern const char *acpi_gbl_ppc_decode[];
+extern const char *acpi_gbl_ior_decode[];
+extern const char *acpi_gbl_dts_decode[];
+extern const char *acpi_gbl_ct_decode[];
+extern const char *acpi_gbl_sbt_decode[];
+extern const char *acpi_gbl_am_decode[];
+extern const char *acpi_gbl_sm_decode[];
+extern const char *acpi_gbl_wm_decode[];
+extern const char *acpi_gbl_cph_decode[];
+extern const char *acpi_gbl_cpo_decode[];
+extern const char *acpi_gbl_dp_decode[];
+extern const char *acpi_gbl_ed_decode[];
+extern const char *acpi_gbl_bpb_decode[];
+extern const char *acpi_gbl_sb_decode[];
+extern const char *acpi_gbl_fc_decode[];
+extern const char *acpi_gbl_pt_decode[];
 #endif
 
 /* Types for Resource descriptor entries */
@@ -79,14 +95,14 @@ extern const char *acpi_gbl_typ_decode[];
 #define ACPI_SMALL_VARIABLE_LENGTH      3
 
 typedef
-acpi_status(*acpi_walk_aml_callback) (u8 * aml,
+acpi_status(*acpi_walk_aml_callback) (u8 *aml,
                                      u32 length,
                                      u32 offset,
                                      u8 resource_index, void **context);
 
 typedef
 acpi_status(*acpi_pkg_callback) (u8 object_type,
-                                union acpi_operand_object * source_object,
+                                union acpi_operand_object *source_object,
                                 union acpi_generic_state * state,
                                 void *context);
 
@@ -202,7 +218,9 @@ extern const u8 _acpi_ctype[];
 #define ACPI_IS_PRINT(c)  (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP | _ACPI_DI | _ACPI_SP | _ACPI_PU))
 #define ACPI_IS_ALPHA(c)  (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP))
 
-#endif                         /* ACPI_USE_SYSTEM_CLIBRARY */
+#endif                         /* !ACPI_USE_SYSTEM_CLIBRARY */
+
+#define ACPI_IS_ASCII(c)  ((c) < 0x80)
 
 /*
  * utcopy - Object construction and conversion interfaces
@@ -210,11 +228,11 @@ extern const u8 _acpi_ctype[];
 acpi_status
 acpi_ut_build_simple_object(union acpi_operand_object *obj,
                            union acpi_object *user_obj,
-                           u8 * data_space, u32 * buffer_space_used);
+                           u8 *data_space, u32 *buffer_space_used);
 
 acpi_status
 acpi_ut_build_package_object(union acpi_operand_object *obj,
-                            u8 * buffer, u32 * space_used);
+                            u8 *buffer, u32 *space_used);
 
 acpi_status
 acpi_ut_copy_iobject_to_eobject(union acpi_operand_object *obj,
@@ -287,9 +305,10 @@ acpi_ut_ptr_exit(u32 line_number,
                 const char *function_name,
                 const char *module_name, u32 component_id, u8 *ptr);
 
-void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id);
+void
+acpi_ut_debug_dump_buffer(u8 *buffer, u32 count, u32 display, u32 component_id);
 
-void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display);
+void acpi_ut_dump_buffer(u8 *buffer, u32 count, u32 display, u32 offset);
 
 void acpi_ut_report_error(char *module_name, u32 line_number);
 
@@ -337,15 +356,19 @@ acpi_ut_execute_power_methods(struct acpi_namespace_node *device_node,
  */
 acpi_status
 acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
-                   struct acpica_device_id **return_id);
+                   struct acpi_pnp_device_id ** return_id);
 
 acpi_status
 acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
-                   struct acpica_device_id **return_id);
+                   struct acpi_pnp_device_id ** return_id);
+
+acpi_status
+acpi_ut_execute_SUB(struct acpi_namespace_node *device_node,
+                   struct acpi_pnp_device_id **return_id);
 
 acpi_status
 acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
-                   struct acpica_device_id_list **return_cid_list);
+                   struct acpi_pnp_device_id_list ** return_cid_list);
 
 /*
  * utlock - reader/writer locks
@@ -479,15 +502,19 @@ acpi_ut_walk_package_tree(union acpi_operand_object *source_object,
 
 void acpi_ut_strupr(char *src_string);
 
+void acpi_ut_strlwr(char *src_string);
+
+int acpi_ut_stricmp(char *string1, char *string2);
+
 void acpi_ut_print_string(char *string, u8 max_length);
 
 u8 acpi_ut_valid_acpi_name(u32 name);
 
-acpi_name acpi_ut_repair_name(char *name);
+void acpi_ut_repair_name(char *name);
 
 u8 acpi_ut_valid_acpi_char(char character, u32 position);
 
-acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 * ret_integer);
+acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer);
 
 /* Values for Base above (16=Hex, 10=Decimal) */
 
@@ -508,12 +535,12 @@ acpi_ut_display_init_pathname(u8 type,
  * utresrc
  */
 acpi_status
-acpi_ut_walk_aml_resources(u8 * aml,
+acpi_ut_walk_aml_resources(u8 *aml,
                           acpi_size aml_length,
                           acpi_walk_aml_callback user_function,
                           void **context);
 
-acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index);
+acpi_status acpi_ut_validate_resource(void *aml, u8 *return_index);
 
 u32 acpi_ut_get_descriptor_length(void *aml);
 
@@ -524,8 +551,7 @@ u8 acpi_ut_get_resource_header_length(void *aml);
 u8 acpi_ut_get_resource_type(void *aml);
 
 acpi_status
-acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc,
-                            u8 ** end_tag);
+acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc, u8 **end_tag);
 
 /*
  * utmutex - mutex support
index af49479..9684496 100644 (file)
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: amlresrc.h - AML resource descriptors
index 465f021..57895db 100644 (file)
@@ -280,7 +280,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
 
                        /*
                         * Get the return value and save as the last result
-                        * value.  This is the only place where walk_state->return_desc
+                        * value. This is the only place where walk_state->return_desc
                         * is set to anything other than zero!
                         */
                        walk_state->return_desc = walk_state->operands[0];
index 3da6fd8..b5b904e 100644 (file)
@@ -277,7 +277,7 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Process all named fields in a field declaration.  Names are
+ * DESCRIPTION: Process all named fields in a field declaration. Names are
  *              entered into the namespace.
  *
  ******************************************************************************/
index aa9a5d4..52eb4e0 100644 (file)
@@ -170,7 +170,7 @@ acpi_ds_create_method_mutex(union acpi_operand_object *method_desc)
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Prepare a method for execution.  Parses the method if necessary,
+ * DESCRIPTION: Prepare a method for execution. Parses the method if necessary,
  *              increments the thread count, and waits at the method semaphore
  *              for clearance to execute.
  *
@@ -444,7 +444,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
  * RETURN:      Status
  *
  * DESCRIPTION: Restart a method that was preempted by another (nested) method
- *              invocation.  Handle the return value (if any) from the callee.
+ *              invocation. Handle the return value (if any) from the callee.
  *
  ******************************************************************************/
 
@@ -530,7 +530,7 @@ acpi_ds_restart_control_method(struct acpi_walk_state *walk_state,
  *
  * RETURN:      None
  *
- * DESCRIPTION: Terminate a control method.  Delete everything that the method
+ * DESCRIPTION: Terminate a control method. Delete everything that the method
  *              created, delete all locals and arguments, and delete the parse
  *              tree if requested.
  *
index 8d55ceb..9a83b7e 100644 (file)
@@ -76,7 +76,7 @@ acpi_ds_method_data_get_type(u16 opcode,
  * RETURN:      Status
  *
  * DESCRIPTION: Initialize the data structures that hold the method's arguments
- *              and locals.  The data struct is an array of namespace nodes for
+ *              and locals. The data struct is an array of namespace nodes for
  *              each - this allows ref_of and de_ref_of to work properly for these
  *              special data types.
  *
@@ -129,7 +129,7 @@ void acpi_ds_method_data_init(struct acpi_walk_state *walk_state)
  *
  * RETURN:      None
  *
- * DESCRIPTION: Delete method locals and arguments.  Arguments are only
+ * DESCRIPTION: Delete method locals and arguments. Arguments are only
  *              deleted if this method was called from another method.
  *
  ******************************************************************************/
@@ -183,7 +183,7 @@ void acpi_ds_method_data_delete_all(struct acpi_walk_state *walk_state)
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Initialize arguments for a method.  The parameter list is a list
+ * DESCRIPTION: Initialize arguments for a method. The parameter list is a list
  *              of ACPI operand objects, either null terminated or whose length
  *              is defined by max_param_count.
  *
@@ -401,7 +401,7 @@ acpi_ds_method_data_get_value(u8 type,
                 * This means that either 1) The expected argument was
                 * not passed to the method, or 2) A local variable
                 * was referenced by the method (via the ASL)
-                * before it was initialized.  Either case is an error.
+                * before it was initialized. Either case is an error.
                 */
 
                /* If slack enabled, init the local_x/arg_x to an Integer of value zero */
@@ -465,7 +465,7 @@ acpi_ds_method_data_get_value(u8 type,
  *
  * RETURN:      None
  *
- * DESCRIPTION: Delete the entry at Opcode:Index.  Inserts
+ * DESCRIPTION: Delete the entry at Opcode:Index. Inserts
  *              a null into the stack slot after the object is deleted.
  *
  ******************************************************************************/
@@ -523,7 +523,7 @@ acpi_ds_method_data_delete_value(u8 type,
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Store a value in an Arg or Local.  The obj_desc is installed
+ * DESCRIPTION: Store a value in an Arg or Local. The obj_desc is installed
  *              as the new value for the Arg or Local and the reference count
  *              for obj_desc is incremented.
  *
@@ -566,7 +566,7 @@ acpi_ds_store_object_to_local(u8 type,
 
        /*
         * If the reference count on the object is more than one, we must
-        * take a copy of the object before we store.  A reference count
+        * take a copy of the object before we store. A reference count
         * of exactly 1 means that the object was just created during the
         * evaluation of an expression, and we can safely use it since it
         * is not used anywhere else.
index 68592dd..c9f15d3 100644 (file)
@@ -293,7 +293,7 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state,
 
        /*
         * Second arg is the buffer data (optional) byte_list can be either
-        * individual bytes or a string initializer.  In either case, a
+        * individual bytes or a string initializer. In either case, a
         * byte_list appears in the AML.
         */
        arg = op->common.value.arg;     /* skip first arg */
@@ -568,7 +568,7 @@ acpi_ds_create_node(struct acpi_walk_state *walk_state,
 
        /*
         * Because of the execution pass through the non-control-method
-        * parts of the table, we can arrive here twice.  Only init
+        * parts of the table, we can arrive here twice. Only init
         * the named object node the first time through
         */
        if (acpi_ns_get_attached_object(node)) {
@@ -618,7 +618,7 @@ acpi_ds_create_node(struct acpi_walk_state *walk_state,
  * RETURN:      Status
  *
  * DESCRIPTION: Initialize a namespace object from a parser Op and its
- *              associated arguments.  The namespace object is a more compact
+ *              associated arguments. The namespace object is a more compact
  *              representation of the Op and its arguments.
  *
  ******************************************************************************/
index aa34d89..0df024e 100644 (file)
@@ -649,7 +649,8 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
                    ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) &&
                     (op->common.parent->common.aml_opcode !=
                      AML_VAR_PACKAGE_OP)
-                    && (op->common.parent->common.aml_opcode != AML_NAME_OP))) {
+                    && (op->common.parent->common.aml_opcode !=
+                        AML_NAME_OP))) {
                        walk_state->result_obj = obj_desc;
                }
        }
index 73a5447..afeb99f 100644 (file)
@@ -61,7 +61,7 @@ ACPI_MODULE_NAME("dsutils")
  *
  * RETURN:      None.
  *
- * DESCRIPTION: Clear and remove a reference on an implicit return value.  Used
+ * DESCRIPTION: Clear and remove a reference on an implicit return value. Used
  *              to delete "stale" return values (if enabled, the return value
  *              from every operator is saved at least momentarily, in case the
  *              parent method exits.)
@@ -107,7 +107,7 @@ void acpi_ds_clear_implicit_return(struct acpi_walk_state *walk_state)
  *
  * DESCRIPTION: Implements the optional "implicit return".  We save the result
  *              of every ASL operator and control method invocation in case the
- *              parent method exit.  Before storing a new return value, we
+ *              parent method exit. Before storing a new return value, we
  *              delete the previous return value.
  *
  ******************************************************************************/
@@ -198,7 +198,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
         *
         * If there is no parent, or the parent is a scope_op, we are executing
         * at the method level. An executing method typically has no parent,
-        * since each method is parsed separately.  A method invoked externally
+        * since each method is parsed separately. A method invoked externally
         * via execute_control_method has a scope_op as the parent.
         */
        if ((!op->common.parent) ||
@@ -223,7 +223,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
        }
 
        /*
-        * Decide what to do with the result based on the parent.  If
+        * Decide what to do with the result based on the parent. If
         * the parent opcode will not use the result, delete the object.
         * Otherwise leave it as is, it will be deleted when it is used
         * as an operand later.
@@ -266,7 +266,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
 
                /*
                 * These opcodes allow term_arg(s) as operands and therefore
-                * the operands can be method calls.  The result is used.
+                * the operands can be method calls. The result is used.
                 */
                goto result_used;
 
@@ -284,7 +284,7 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
                        AML_BANK_FIELD_OP)) {
                        /*
                         * These opcodes allow term_arg(s) as operands and therefore
-                        * the operands can be method calls.  The result is used.
+                        * the operands can be method calls. The result is used.
                         */
                        goto result_used;
                }
@@ -329,9 +329,9 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Used after interpretation of an opcode.  If there is an internal
+ * DESCRIPTION: Used after interpretation of an opcode. If there is an internal
  *              result descriptor, check if the parent opcode will actually use
- *              this result.  If not, delete the result now so that it will
+ *              this result. If not, delete the result now so that it will
  *              not become orphaned.
  *
  ******************************************************************************/
@@ -376,7 +376,7 @@ acpi_ds_delete_result_if_not_used(union acpi_parse_object *op,
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Resolve all operands to their values.  Used to prepare
+ * DESCRIPTION: Resolve all operands to their values. Used to prepare
  *              arguments to a control method invocation (a call from one
  *              method to another.)
  *
@@ -391,7 +391,7 @@ acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state)
 
        /*
         * Attempt to resolve each of the valid operands
-        * Method arguments are passed by reference, not by value.  This means
+        * Method arguments are passed by reference, not by value. This means
         * that the actual objects are passed, not copies of the objects.
         */
        for (i = 0; i < walk_state->num_operands; i++) {
@@ -451,7 +451,7 @@ void acpi_ds_clear_operands(struct acpi_walk_state *walk_state)
  * RETURN:      Status
  *
  * DESCRIPTION: Translate a parse tree object that is an argument to an AML
- *              opcode to the equivalent interpreter object.  This may include
+ *              opcode to the equivalent interpreter object. This may include
  *              looking up a name or entering a new name into the internal
  *              namespace.
  *
@@ -496,9 +496,9 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
                /*
                 * Special handling for buffer_field declarations. This is a deferred
                 * opcode that unfortunately defines the field name as the last
-                * parameter instead of the first.  We get here when we are performing
+                * parameter instead of the first. We get here when we are performing
                 * the deferred execution, so the actual name of the field is already
-                * in the namespace.  We don't want to attempt to look it up again
+                * in the namespace. We don't want to attempt to look it up again
                 * because we may be executing in a different scope than where the
                 * actual opcode exists.
                 */
@@ -560,7 +560,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
                                         * indicate this to the interpreter, set the
                                         * object to the root
                                         */
-                                       obj_desc = ACPI_CAST_PTR(union
+                                       obj_desc =
+                                           ACPI_CAST_PTR(union
                                                                 acpi_operand_object,
                                                                 acpi_gbl_root_node);
                                        status = AE_OK;
@@ -604,8 +605,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
                        /*
                         * If the name is null, this means that this is an
                         * optional result parameter that was not specified
-                        * in the original ASL.  Create a Zero Constant for a
-                        * placeholder.  (Store to a constant is a Noop.)
+                        * in the original ASL. Create a Zero Constant for a
+                        * placeholder. (Store to a constant is a Noop.)
                         */
                        opcode = AML_ZERO_OP;   /* Has no arguments! */
 
index 642f3c0..5859393 100644 (file)
@@ -57,7 +57,7 @@ ACPI_MODULE_NAME("dswexec")
 /*
  * Dispatch table for opcode classes
  */
-static ACPI_EXECUTE_OP acpi_gbl_op_type_dispatch[] = {
+static acpi_execute_op acpi_gbl_op_type_dispatch[] = {
        acpi_ex_opcode_0A_0T_1R,
        acpi_ex_opcode_1A_0T_0R,
        acpi_ex_opcode_1A_0T_1R,
@@ -204,7 +204,7 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state,
  * RETURN:      Status
  *
  * DESCRIPTION: Descending callback used during the execution of control
- *              methods.  This is where most operators and operands are
+ *              methods. This is where most operators and operands are
  *              dispatched to the interpreter.
  *
  ****************************************************************************/
@@ -297,7 +297,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
                if (walk_state->walk_type & ACPI_WALK_METHOD) {
                        /*
                         * Found a named object declaration during method execution;
-                        * we must enter this object into the namespace.  The created
+                        * we must enter this object into the namespace. The created
                         * object is temporary and will be deleted upon completion of
                         * the execution of this method.
                         *
@@ -348,7 +348,7 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
  * RETURN:      Status
  *
  * DESCRIPTION: Ascending callback used during the execution of control
- *              methods.  The only thing we really need to do here is to
+ *              methods. The only thing we really need to do here is to
  *              notice the beginning of IF, ELSE, and WHILE blocks.
  *
  ****************************************************************************/
@@ -432,7 +432,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
                if (ACPI_SUCCESS(status)) {
                        /*
                         * Dispatch the request to the appropriate interpreter handler
-                        * routine.  There is one routine per opcode "type" based upon the
+                        * routine. There is one routine per opcode "type" based upon the
                         * number of opcode arguments and return type.
                         */
                        status =
index 89c0114..3798357 100644 (file)
@@ -254,7 +254,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
                                    acpi_ut_get_type_name(node->type),
                                    acpi_ut_get_node_name(node)));
 
-                       return (AE_AML_OPERAND_TYPE);
+                       return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
                }
                break;
 
@@ -602,7 +602,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
                                                          region_space,
                                                          walk_state);
                                if (ACPI_FAILURE(status)) {
-                                       return (status);
+                                       return_ACPI_STATUS(status);
                                }
 
                                acpi_ex_exit_interpreter();
index d0e6555..3e65a15 100644 (file)
@@ -51,8 +51,9 @@
 ACPI_MODULE_NAME("dswstate")
 
   /* Local prototypes */
-static acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *ws);
-static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *ws);
+static acpi_status
+acpi_ds_result_stack_push(struct acpi_walk_state *walk_state);
+static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state);
 
 /*******************************************************************************
  *
@@ -347,7 +348,7 @@ acpi_ds_obj_stack_push(void *object, struct acpi_walk_state * walk_state)
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Pop this walk's object stack.  Objects on the stack are NOT
+ * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT
  *              deleted by this routine.
  *
  ******************************************************************************/
@@ -491,7 +492,7 @@ acpi_ds_push_walk_state(struct acpi_walk_state *walk_state,
  * RETURN:      A walk_state object popped from the thread's stack
  *
  * DESCRIPTION: Remove and return the walkstate object that is at the head of
- *              the walk stack for the given walk list.  NULL indicates that
+ *              the walk stack for the given walk list. NULL indicates that
  *              the list is empty.
  *
  ******************************************************************************/
@@ -531,14 +532,17 @@ struct acpi_walk_state *acpi_ds_pop_walk_state(struct acpi_thread_state *thread)
  *
  * RETURN:      Pointer to the new walk state.
  *
- * DESCRIPTION: Allocate and initialize a new walk state.  The current walk
+ * DESCRIPTION: Allocate and initialize a new walk state. The current walk
  *              state is set to this new state.
  *
  ******************************************************************************/
 
-struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union acpi_parse_object
-                                                 *origin, union acpi_operand_object
-                                                 *method_desc, struct acpi_thread_state
+struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id,
+                                                 union acpi_parse_object
+                                                 *origin,
+                                                 union acpi_operand_object
+                                                 *method_desc,
+                                                 struct acpi_thread_state
                                                  *thread)
 {
        struct acpi_walk_state *walk_state;
@@ -653,7 +657,7 @@ acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state,
                /*
                 * Setup the current scope.
                 * Find a Named Op that has a namespace node associated with it.
-                * search upwards from this Op.  Current scope is the first
+                * search upwards from this Op. Current scope is the first
                 * Op with a namespace node.
                 */
                extra_op = parser_state->start_op;
@@ -704,13 +708,13 @@ void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state)
        ACPI_FUNCTION_TRACE_PTR(ds_delete_walk_state, walk_state);
 
        if (!walk_state) {
-               return;
+               return_VOID;
        }
 
        if (walk_state->descriptor_type != ACPI_DESC_TYPE_WALK) {
                ACPI_ERROR((AE_INFO, "%p is not a valid walk state",
                            walk_state));
-               return;
+               return_VOID;
        }
 
        /* There should not be any open scopes */
index ef0193d..36d1205 100644 (file)
@@ -89,7 +89,8 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info)
        /* Set the mask bit only if there are references to this GPE */
 
        if (gpe_event_info->runtime_count) {
-               ACPI_SET_BIT(gpe_register_info->enable_for_run, (u8)register_bit);
+               ACPI_SET_BIT(gpe_register_info->enable_for_run,
+                            (u8)register_bit);
        }
 
        return_ACPI_STATUS(AE_OK);
@@ -106,8 +107,7 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_info)
  * DESCRIPTION: Clear a GPE of stale events and enable it.
  *
  ******************************************************************************/
-acpi_status
-acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
+acpi_status acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
 {
        acpi_status status;
 
@@ -131,8 +131,8 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
        }
 
        /* Enable the requested GPE */
-       status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE);
 
+       status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE);
        return_ACPI_STATUS(status);
 }
 
@@ -150,7 +150,8 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
  *
  ******************************************************************************/
 
-acpi_status acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info)
+acpi_status
+acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info)
 {
        acpi_status status = AE_OK;
 
@@ -191,7 +192,8 @@ acpi_status acpi_ev_add_gpe_reference(struct acpi_gpe_event_info *gpe_event_info
  *
  ******************************************************************************/
 
-acpi_status acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info)
+acpi_status
+acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_info)
 {
        acpi_status status = AE_OK;
 
@@ -208,7 +210,8 @@ acpi_status acpi_ev_remove_gpe_reference(struct acpi_gpe_event_info *gpe_event_i
 
                status = acpi_ev_update_gpe_enable_mask(gpe_event_info);
                if (ACPI_SUCCESS(status)) {
-                       status = acpi_hw_low_set_gpe(gpe_event_info,
+                       status =
+                           acpi_hw_low_set_gpe(gpe_event_info,
                                                     ACPI_GPE_DISABLE);
                }
 
@@ -306,7 +309,8 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
 
        /* A Non-NULL gpe_device means this is a GPE Block Device */
 
-       obj_desc = acpi_ns_get_attached_object((struct acpi_namespace_node *)
+       obj_desc =
+           acpi_ns_get_attached_object((struct acpi_namespace_node *)
                                               gpe_device);
        if (!obj_desc || !obj_desc->device.gpe_block) {
                return (NULL);
index 8cf4c10..1571a61 100644 (file)
@@ -486,7 +486,8 @@ acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
                        if (ACPI_FAILURE(status)) {
                                ACPI_EXCEPTION((AE_INFO, status,
                                        "Could not enable GPE 0x%02X",
-                                       gpe_index + gpe_block->block_base_number));
+                                       gpe_index +
+                                       gpe_block->block_base_number));
                                continue;
                        }
 
index cb50dd9..228a0c3 100644 (file)
@@ -374,7 +374,8 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
                                gpe_event_info->dispatch.handler = NULL;
                                gpe_event_info->flags &=
                                    ~ACPI_GPE_DISPATCH_MASK;
-                       } else if ((gpe_event_info->
+                       } else
+                           if ((gpe_event_info->
                                 flags & ACPI_GPE_DISPATCH_MASK) ==
                                ACPI_GPE_DISPATCH_NOTIFY) {
 
index 4c1c826..1474241 100644 (file)
@@ -227,8 +227,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
 
                                /* Install a handler for this PCI root bridge */
 
-                               status =
-                                   acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
+                               status = acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
                                if (ACPI_FAILURE(status)) {
                                        if (status == AE_SAME_HANDLER) {
                                                /*
@@ -350,8 +349,8 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
 static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node)
 {
        acpi_status status;
-       struct acpica_device_id *hid;
-       struct acpica_device_id_list *cid;
+       struct acpi_pnp_device_id *hid;
+       struct acpi_pnp_device_id_list *cid;
        u32 i;
        u8 match;
 
index 7587eb6..ae668f3 100644 (file)
@@ -398,7 +398,7 @@ ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
  *
  ******************************************************************************/
 acpi_status
-acpi_install_global_event_handler(ACPI_GBL_EVENT_HANDLER handler, void *context)
+acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context)
 {
        acpi_status status;
 
index 87c5f23..3f30e75 100644 (file)
@@ -221,7 +221,8 @@ acpi_setup_gpe_for_wake(acpi_handle wake_device,
        if (wake_device == ACPI_ROOT_OBJECT) {
                device_node = acpi_gbl_root_node;
        } else {
-               device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device);
+               device_node =
+                   ACPI_CAST_PTR(struct acpi_namespace_node, wake_device);
        }
 
        /* Validate WakeDevice is of type Device */
@@ -324,7 +325,8 @@ ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake)
  *
  ******************************************************************************/
 
-acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action)
+acpi_status
+acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action)
 {
        acpi_status status = AE_OK;
        struct acpi_gpe_event_info *gpe_event_info;
@@ -567,7 +569,7 @@ acpi_install_gpe_block(acpi_handle gpe_device,
 
        status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
        if (ACPI_FAILURE(status)) {
-               return (status);
+               return_ACPI_STATUS(status);
        }
 
        node = acpi_ns_validate_handle(gpe_device);
@@ -650,7 +652,7 @@ acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
 
        status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
        if (ACPI_FAILURE(status)) {
-               return (status);
+               return_ACPI_STATUS(status);
        }
 
        node = acpi_ns_validate_handle(gpe_device);
@@ -694,8 +696,7 @@ ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
  *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
  *
  ******************************************************************************/
-acpi_status
-acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
+acpi_status acpi_get_gpe_device(u32 index, acpi_handle * gpe_device)
 {
        struct acpi_gpe_device_info info;
        acpi_status status;
index bfb062e..4492a4e 100644 (file)
@@ -516,8 +516,8 @@ acpi_ex_convert_to_string(union acpi_operand_object * obj_desc,
                        string_length--;
                }
 
-               return_desc = acpi_ut_create_string_object((acpi_size)
-                                                          string_length);
+               return_desc =
+                   acpi_ut_create_string_object((acpi_size) string_length);
                if (!return_desc) {
                        return_ACPI_STATUS(AE_NO_MEMORY);
                }
index 691d476..66554bc 100644 (file)
@@ -78,7 +78,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
            (target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
                /*
                 * Dereference an existing alias so that we don't create a chain
-                * of aliases.  With this code, we guarantee that an alias is
+                * of aliases. With this code, we guarantee that an alias is
                 * always exactly one level of indirection away from the
                 * actual aliased name.
                 */
@@ -90,7 +90,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
        /*
         * For objects that can never change (i.e., the NS node will
         * permanently point to the same object), we can simply attach
-        * the object to the new NS node.  For other objects (such as
+        * the object to the new NS node. For other objects (such as
         * Integers, buffers, etc.), we have to point the Alias node
         * to the original Node.
         */
@@ -139,7 +139,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
 
                /*
                 * The new alias assumes the type of the target, and it points
-                * to the same object.  The reference count of the object has an
+                * to the same object. The reference count of the object has an
                 * additional reference to prevent deletion out from under either the
                 * target node or the alias Node
                 */
@@ -243,8 +243,7 @@ acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state)
 
        /* Init object and attach to NS node */
 
-       obj_desc->mutex.sync_level =
-           (u8) walk_state->operands[1]->integer.value;
+       obj_desc->mutex.sync_level = (u8)walk_state->operands[1]->integer.value;
        obj_desc->mutex.node =
            (struct acpi_namespace_node *)walk_state->operands[0];
 
index bc5b9a6..d7c9f51 100644 (file)
@@ -145,10 +145,10 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
        case ACPI_TYPE_BUFFER:
 
                acpi_os_printf("[0x%.2X]\n", (u32)source_desc->buffer.length);
-               acpi_ut_dump_buffer2(source_desc->buffer.pointer,
-                                    (source_desc->buffer.length < 256) ?
-                                    source_desc->buffer.length : 256,
-                                    DB_BYTE_DISPLAY);
+               acpi_ut_dump_buffer(source_desc->buffer.pointer,
+                                   (source_desc->buffer.length < 256) ?
+                                   source_desc->buffer.length : 256,
+                                   DB_BYTE_DISPLAY, 0);
                break;
 
        case ACPI_TYPE_STRING:
@@ -190,7 +190,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
 
                        acpi_os_printf("Table Index 0x%X\n",
                                       source_desc->reference.value);
-                       return;
+                       return_VOID;
 
                default:
                        break;
index 213c081..858b43a 100644 (file)
@@ -464,7 +464,8 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth)
 
        ACPI_FUNCTION_NAME(ex_dump_operand)
 
-           if (!((ACPI_LV_EXEC & acpi_dbg_level)
+           if (!
+               ((ACPI_LV_EXEC & acpi_dbg_level)
                  && (_COMPONENT & acpi_dbg_layer))) {
                return;
        }
@@ -777,7 +778,7 @@ acpi_ex_dump_operands(union acpi_operand_object **operands,
  * PARAMETERS:  title               - Descriptive text
  *              value               - Value to be displayed
  *
- * DESCRIPTION: Object dump output formatting functions.  These functions
+ * DESCRIPTION: Object dump output formatting functions. These functions
  *              reduce the number of format strings required and keeps them
  *              all in one place for easy modification.
  *
@@ -810,7 +811,8 @@ void acpi_ex_dump_namespace_node(struct acpi_namespace_node *node, u32 flags)
        ACPI_FUNCTION_ENTRY();
 
        if (!flags) {
-               if (!((ACPI_LV_OBJECTS & acpi_dbg_level)
+               if (!
+                   ((ACPI_LV_OBJECTS & acpi_dbg_level)
                      && (_COMPONENT & acpi_dbg_layer))) {
                        return;
                }
@@ -940,10 +942,11 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc,
                acpi_os_printf("[Buffer] Length %.2X = ",
                               obj_desc->buffer.length);
                if (obj_desc->buffer.length) {
-                       acpi_ut_dump_buffer(ACPI_CAST_PTR
-                                           (u8, obj_desc->buffer.pointer),
-                                           obj_desc->buffer.length,
-                                           DB_DWORD_DISPLAY, _COMPONENT);
+                       acpi_ut_debug_dump_buffer(ACPI_CAST_PTR
+                                                 (u8,
+                                                  obj_desc->buffer.pointer),
+                                                 obj_desc->buffer.length,
+                                                 DB_DWORD_DISPLAY, _COMPONENT);
                } else {
                        acpi_os_printf("\n");
                }
@@ -996,7 +999,8 @@ acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags)
        }
 
        if (!flags) {
-               if (!((ACPI_LV_OBJECTS & acpi_dbg_level)
+               if (!
+                   ((ACPI_LV_OBJECTS & acpi_dbg_level)
                      && (_COMPONENT & acpi_dbg_layer))) {
                        return_VOID;
                }
index dc092f5..ebc55fb 100644 (file)
@@ -59,7 +59,7 @@ ACPI_MODULE_NAME("exfield")
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Read from a named field.  Returns either an Integer or a
+ * DESCRIPTION: Read from a named field. Returns either an Integer or a
  *              Buffer, depending on the size of the field.
  *
  ******************************************************************************/
@@ -149,7 +149,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
         * Allocate a buffer for the contents of the field.
         *
         * If the field is larger than the current integer width, create
-        * a BUFFER to hold it.  Otherwise, use an INTEGER.  This allows
+        * a BUFFER to hold it. Otherwise, use an INTEGER. This allows
         * the use of arithmetic operators on the returned value if the
         * field size is equal or smaller than an Integer.
         *
index a778415..aa2ccfb 100644 (file)
@@ -54,8 +54,7 @@ ACPI_MODULE_NAME("exfldio")
 /* Local prototypes */
 static acpi_status
 acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
-                      u32 field_datum_byte_offset,
-                      u64 *value, u32 read_write);
+                      u32 field_datum_byte_offset, u64 *value, u32 read_write);
 
 static u8
 acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value);
@@ -155,7 +154,7 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
 #endif
 
        /*
-        * Validate the request.  The entire request from the byte offset for a
+        * Validate the request. The entire request from the byte offset for a
         * length of one field datum (access width) must fit within the region.
         * (Region length is specified in bytes)
         */
@@ -183,7 +182,7 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
                    obj_desc->common_field.access_byte_width) {
                        /*
                         * This is the case where the access_type (acc_word, etc.) is wider
-                        * than the region itself.  For example, a region of length one
+                        * than the region itself. For example, a region of length one
                         * byte, and a field with Dword access specified.
                         */
                        ACPI_ERROR((AE_INFO,
@@ -321,7 +320,7 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc,
  *
  * DESCRIPTION: Check if a value is out of range of the field being written.
  *              Used to check if the values written to Index and Bank registers
- *              are out of range.  Normally, the value is simply truncated
+ *              are out of range. Normally, the value is simply truncated
  *              to fit the field, but this case is most likely a serious
  *              coding error in the ASL.
  *
@@ -370,7 +369,7 @@ acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value)
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Read or Write a single datum of a field.  The field_type is
+ * DESCRIPTION: Read or Write a single datum of a field. The field_type is
  *              demultiplexed here to handle the different types of fields
  *              (buffer_field, region_field, index_field, bank_field)
  *
@@ -860,7 +859,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
            ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
        /*
         * We must have a buffer that is at least as long as the field
-        * we are writing to.  This is because individual fields are
+        * we are writing to. This is because individual fields are
         * indivisible and partial writes are not supported -- as per
         * the ACPI specification.
         */
@@ -875,7 +874,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
 
                /*
                 * Copy the original data to the new buffer, starting
-                * at Byte zero.  All unused (upper) bytes of the
+                * at Byte zero. All unused (upper) bytes of the
                 * buffer will be 0.
                 */
                ACPI_MEMCPY((char *)new_buffer, (char *)buffer, buffer_length);
index 271c0c5..8405870 100644 (file)
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes
@@ -254,7 +253,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0,
        ACPI_FUNCTION_TRACE(ex_do_concatenate);
 
        /*
-        * Convert the second operand if necessary.  The first operand
+        * Convert the second operand if necessary. The first operand
         * determines the type of the second operand, (See the Data Types
         * section of the ACPI specification.)  Both object types are
         * guaranteed to be either Integer/String/Buffer by the operand
@@ -573,7 +572,7 @@ acpi_ex_do_logical_op(u16 opcode,
        ACPI_FUNCTION_TRACE(ex_do_logical_op);
 
        /*
-        * Convert the second operand if necessary.  The first operand
+        * Convert the second operand if necessary. The first operand
         * determines the type of the second operand, (See the Data Types
         * section of the ACPI 3.0+ specification.)  Both object types are
         * guaranteed to be either Integer/String/Buffer by the operand
index bcceda5..d1f449d 100644 (file)
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exmutex - ASL Mutex Acquire/Release functions
@@ -305,7 +304,7 @@ acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc)
        ACPI_FUNCTION_TRACE(ex_release_mutex_object);
 
        if (obj_desc->mutex.acquisition_depth == 0) {
-               return (AE_NOT_ACQUIRED);
+               return_ACPI_STATUS(AE_NOT_ACQUIRED);
        }
 
        /* Match multiple Acquires with multiple Releases */
@@ -462,7 +461,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
        union acpi_operand_object *next = thread->acquired_mutex_list;
        union acpi_operand_object *obj_desc;
 
-       ACPI_FUNCTION_ENTRY();
+       ACPI_FUNCTION_NAME(ex_release_all_mutexes);
 
        /* Traverse the list of owned mutexes, releasing each one */
 
@@ -474,6 +473,10 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
                obj_desc->mutex.next = NULL;
                obj_desc->mutex.acquisition_depth = 0;
 
+               ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+                                 "Force-releasing held mutex: %p\n",
+                                 obj_desc));
+
                /* Release the mutex, special case for Global Lock */
 
                if (obj_desc == acpi_gbl_global_lock_mutex) {
index fcc75fa..2ff578a 100644 (file)
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exnames - interpreter/scanner name load/execute
@@ -53,8 +52,7 @@ ACPI_MODULE_NAME("exnames")
 /* Local prototypes */
 static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs);
 
-static acpi_status
-acpi_ex_name_segment(u8 ** in_aml_address, char *name_string);
+static acpi_status acpi_ex_name_segment(u8 **in_aml_address, char *name_string);
 
 /*******************************************************************************
  *
@@ -64,7 +62,7 @@ acpi_ex_name_segment(u8 ** in_aml_address, char *name_string);
  *                                    (-1)==root,  0==none
  *              num_name_segs       - count of 4-character name segments
  *
- * RETURN:      A pointer to the allocated string segment.  This segment must
+ * RETURN:      A pointer to the allocated string segment. This segment must
  *              be deleted by the caller.
  *
  * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name
@@ -178,7 +176,8 @@ static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string)
 
        ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Bytes from stream:\n"));
 
-       for (index = 0; (index < ACPI_NAME_SIZE)
+       for (index = 0;
+            (index < ACPI_NAME_SIZE)
             && (acpi_ut_valid_acpi_char(*aml_address, 0)); index++) {
                char_buf[index] = *aml_address++;
                ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "%c\n", char_buf[index]));
index 9ba8c73..bbf01e9 100644 (file)
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exoparg1 - AML execution - opcodes with 1 argument
@@ -606,7 +605,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
                }
 
                /*
-                * Set result to ONES (TRUE) if Value == 0.  Note:
+                * Set result to ONES (TRUE) if Value == 0. Note:
                 * return_desc->Integer.Value is initially == 0 (FALSE) from above.
                 */
                if (!operand[0]->integer.value) {
@@ -618,7 +617,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
        case AML_INCREMENT_OP:  /* Increment (Operand)  */
 
                /*
-                * Create a new integer.  Can't just get the base integer and
+                * Create a new integer. Can't just get the base integer and
                 * increment it because it may be an Arg or Field.
                 */
                return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
@@ -686,7 +685,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
 
                /*
                 * Note: The operand is not resolved at this point because we want to
-                * get the associated object, not its value.  For example, we don't
+                * get the associated object, not its value. For example, we don't
                 * want to resolve a field_unit to its value, we want the actual
                 * field_unit object.
                 */
@@ -727,7 +726,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
 
                /*
                 * The type of the base object must be integer, buffer, string, or
-                * package.  All others are not supported.
+                * package. All others are not supported.
                 *
                 * NOTE: Integer is not specifically supported by the ACPI spec,
                 * but is supported implicitly via implicit operand conversion.
@@ -965,7 +964,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
                                case ACPI_TYPE_PACKAGE:
 
                                        /*
-                                        * Return the referenced element of the package.  We must
+                                        * Return the referenced element of the package. We must
                                         * add another reference to the referenced object, however.
                                         */
                                        return_desc =
index 879e8a2..ee5634a 100644 (file)
@@ -123,7 +123,7 @@ acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state)
                /*
                 * Dispatch the notify to the appropriate handler
                 * NOTE: the request is queued for execution after this method
-                * completes.  The notify handlers are NOT invoked synchronously
+                * completes. The notify handlers are NOT invoked synchronously
                 * from this thread -- because handlers may in turn run other
                 * control methods.
                 */
index 71fcc65..2c89b46 100644 (file)
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exoparg3 - AML execution - opcodes with 3 arguments
@@ -158,7 +157,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state)
        case AML_MID_OP:        /* Mid (Source[0], Index[1], Length[2], Result[3]) */
 
                /*
-                * Create the return object.  The Source operand is guaranteed to be
+                * Create the return object. The Source operand is guaranteed to be
                 * either a String or a Buffer, so just use its type.
                 */
                return_desc = acpi_ut_create_internal_object((operand[0])->
index 0786b86..3e08695 100644 (file)
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exoparg6 - AML execution - opcodes with 6 arguments
@@ -198,7 +197,7 @@ acpi_ex_do_match(u32 match_op,
                return (FALSE);
        }
 
-       return logical_result;
+       return (logical_result);
 }
 
 /*******************************************************************************
@@ -269,7 +268,7 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state)
                 * and the next should be examined.
                 *
                 * Upon finding a match, the loop will terminate via "break" at
-                * the bottom.  If it terminates "normally", match_value will be
+                * the bottom. If it terminates "normally", match_value will be
                 * ACPI_UINT64_MAX (Ones) (its initial value) indicating that no
                 * match was found.
                 */
index 81eca60..ba9db4d 100644 (file)
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exprep - ACPI AML (p-code) execution - field prep utilities
@@ -78,8 +77,8 @@ acpi_ex_generate_access(u32 field_bit_offset,
  *              any_acc keyword.
  *
  * NOTE: Need to have the region_length in order to check for boundary
- *       conditions (end-of-region).  However, the region_length is a deferred
- *       operation.  Therefore, to complete this implementation, the generation
+ *       conditions (end-of-region). However, the region_length is a deferred
+ *       operation. Therefore, to complete this implementation, the generation
  *       of this access width must be deferred until the region length has
  *       been evaluated.
  *
@@ -308,7 +307,7 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc,
  * RETURN:      Status
  *
  * DESCRIPTION: Initialize the areas of the field object that are common
- *              to the various types of fields.  Note: This is very "sensitive"
+ *              to the various types of fields. Note: This is very "sensitive"
  *              code because we are solving the general case for field
  *              alignment.
  *
@@ -336,13 +335,13 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
        obj_desc->common_field.bit_length = field_bit_length;
 
        /*
-        * Decode the access type so we can compute offsets.  The access type gives
+        * Decode the access type so we can compute offsets. The access type gives
         * two pieces of information - the width of each field access and the
         * necessary byte_alignment (address granularity) of the access.
         *
         * For any_acc, the access_bit_width is the largest width that is both
         * necessary and possible in an attempt to access the whole field in one
-        * I/O operation.  However, for any_acc, the byte_alignment is always one
+        * I/O operation. However, for any_acc, the byte_alignment is always one
         * byte.
         *
         * For all Buffer Fields, the byte_alignment is always one byte.
@@ -363,7 +362,7 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
 
        /*
         * base_byte_offset is the address of the start of the field within the
-        * region.  It is the byte address of the first *datum* (field-width data
+        * region. It is the byte address of the first *datum* (field-width data
         * unit) of the field. (i.e., the first datum that contains at least the
         * first *bit* of the field.)
         *
index 1f1ce0c..1db2c0b 100644 (file)
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exregion - ACPI default op_region (address space) handlers
@@ -202,7 +201,7 @@ acpi_ex_system_memory_space_handler(u32 function,
         * Perform the memory read or write
         *
         * Note: For machines that do not support non-aligned transfers, the target
-        * address was checked for alignment above.  We do not attempt to break the
+        * address was checked for alignment above. We do not attempt to break the
         * transfer up into smaller (byte-size) chunks because the AML specifically
         * asked for a transfer width that the hardware may require.
         */
index fa50e77..6239956 100644 (file)
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exresnte - AML Interpreter object resolution
@@ -58,8 +57,8 @@ ACPI_MODULE_NAME("exresnte")
  * PARAMETERS:  object_ptr      - Pointer to a location that contains
  *                                a pointer to a NS node, and will receive a
  *                                pointer to the resolved object.
- *              walk_state      - Current state.  Valid only if executing AML
- *                                code.  NULL if simply resolving an object
+ *              walk_state      - Current state. Valid only if executing AML
+ *                                code. NULL if simply resolving an object
  *
  * RETURN:      Status
  *
@@ -67,7 +66,7 @@ ACPI_MODULE_NAME("exresnte")
  *
  * Note: for some of the data types, the pointer attached to the Node
  * can be either a pointer to an actual internal object or a pointer into the
- * AML stream itself.  These types are currently:
+ * AML stream itself. These types are currently:
  *
  *      ACPI_TYPE_INTEGER
  *      ACPI_TYPE_STRING
@@ -89,7 +88,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
        ACPI_FUNCTION_TRACE(ex_resolve_node_to_value);
 
        /*
-        * The stack pointer points to a struct acpi_namespace_node (Node).  Get the
+        * The stack pointer points to a struct acpi_namespace_node (Node). Get the
         * object that is attached to the Node.
         */
        node = *object_ptr;
index bbf40ac..cc176b2 100644 (file)
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exresolv - AML Interpreter object resolution
@@ -327,7 +326,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Return the base object and type.  Traverse a reference list if
+ * DESCRIPTION: Return the base object and type. Traverse a reference list if
  *              necessary to get to the base object.
  *
  ******************************************************************************/
index f232fba..b9ebff2 100644 (file)
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exresop - AML Interpreter operand/object resolution
@@ -87,7 +86,7 @@ acpi_ex_check_object_type(acpi_object_type type_needed,
        if (type_needed == ACPI_TYPE_LOCAL_REFERENCE) {
                /*
                 * Allow the AML "Constant" opcodes (Zero, One, etc.) to be reference
-                * objects and thus allow them to be targets.  (As per the ACPI
+                * objects and thus allow them to be targets. (As per the ACPI
                 * specification, a store to a constant is a noop.)
                 */
                if ((this_type == ACPI_TYPE_INTEGER) &&
@@ -337,7 +336,8 @@ acpi_ex_resolve_operands(u16 opcode,
                        if ((opcode == AML_STORE_OP) &&
                            ((*stack_ptr)->common.type ==
                             ACPI_TYPE_LOCAL_REFERENCE)
-                           && ((*stack_ptr)->reference.class == ACPI_REFCLASS_INDEX)) {
+                           && ((*stack_ptr)->reference.class ==
+                               ACPI_REFCLASS_INDEX)) {
                                goto next_operand;
                        }
                        break;
@@ -638,7 +638,7 @@ acpi_ex_resolve_operands(u16 opcode,
                                if (acpi_gbl_enable_interpreter_slack) {
                                        /*
                                         * Enable original behavior of Store(), allowing any and all
-                                        * objects as the source operand.  The ACPI spec does not
+                                        * objects as the source operand. The ACPI spec does not
                                         * allow this, however.
                                         */
                                        break;
index 5fffe7a..90431f1 100644 (file)
@@ -374,7 +374,7 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
  *              with the input value.
  *
  *              When storing into an object the data is converted to the
- *              target object type then stored in the object.  This means
+ *              target object type then stored in the object. This means
  *              that the target object type (for an initialized target) will
  *              not be changed by a store operation.
  *
@@ -491,7 +491,7 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
                                  acpi_ut_get_object_type_name(source_desc),
                                  source_desc, node));
 
-               /* No conversions for all other types.  Just attach the source object */
+               /* No conversions for all other types. Just attach the source object */
 
                status = acpi_ns_attach_object(node, source_desc,
                                               source_desc->common.type);
index b35bed5..87153bb 100644 (file)
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exstoren - AML Interpreter object store support,
@@ -61,7 +60,7 @@ ACPI_MODULE_NAME("exstoren")
  *
  * RETURN:      Status, resolved object in source_desc_ptr.
  *
- * DESCRIPTION: Resolve an object.  If the object is a reference, dereference
+ * DESCRIPTION: Resolve an object. If the object is a reference, dereference
  *              it and return the actual object in the source_desc_ptr.
  *
  ******************************************************************************/
@@ -93,7 +92,7 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr,
 
                /*
                 * Stores into a Field/Region or into a Integer/Buffer/String
-                * are all essentially the same.  This case handles the
+                * are all essentially the same. This case handles the
                 * "interchangeable" types Integer, String, and Buffer.
                 */
                if (source_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) {
@@ -167,7 +166,7 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr,
  *
  * RETURN:      Status
  *
- * DESCRIPTION: "Store" an object to another object.  This may include
+ * DESCRIPTION: "Store" an object to another object. This may include
  *              converting the source type to the target type (implicit
  *              conversion), and a copy of the value of the source to
  *              the target.
@@ -178,14 +177,14 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr,
  *              with the input value.
  *
  *              When storing into an object the data is converted to the
- *              target object type then stored in the object.  This means
+ *              target object type then stored in the object. This means
  *              that the target object type (for an initialized target) will
  *              not be changed by a store operation.
  *
  *              This module allows destination types of Number, String,
  *              Buffer, and Package.
  *
- *              Assumes parameters are already validated.  NOTE: source_desc
+ *              Assumes parameters are already validated. NOTE: source_desc
  *              resolution (from a reference object) must be performed by
  *              the caller if necessary.
  *
index 53c2484..b5f339c 100644 (file)
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exstorob - AML Interpreter object store support, store to object
@@ -108,7 +107,7 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc,
 #ifdef ACPI_OBSOLETE_BEHAVIOR
                /*
                 * NOTE: ACPI versions up to 3.0 specified that the buffer must be
-                * truncated if the string is smaller than the buffer.  However, "other"
+                * truncated if the string is smaller than the buffer. However, "other"
                 * implementations of ACPI never did this and thus became the defacto
                 * standard. ACPI 3.0A changes this behavior such that the buffer
                 * is no longer truncated.
@@ -117,7 +116,7 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc,
                /*
                 * OBSOLETE BEHAVIOR:
                 * If the original source was a string, we must truncate the buffer,
-                * according to the ACPI spec.  Integer-to-Buffer and Buffer-to-Buffer
+                * according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer
                 * copy must not truncate the original buffer.
                 */
                if (original_src_type == ACPI_TYPE_STRING) {
index b760641..c8a0ad5 100644 (file)
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exsystem - Interface to OS services
@@ -59,7 +58,7 @@ ACPI_MODULE_NAME("exsystem")
  * RETURN:      Status
  *
  * DESCRIPTION: Implements a semaphore wait with a check to see if the
- *              semaphore is available immediately.  If it is not, the
+ *              semaphore is available immediately. If it is not, the
  *              interpreter is released before waiting.
  *
  ******************************************************************************/
@@ -104,7 +103,7 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout)
  * RETURN:      Status
  *
  * DESCRIPTION: Implements a mutex wait with a check to see if the
- *              mutex is available immediately.  If it is not, the
+ *              mutex is available immediately. If it is not, the
  *              interpreter is released before waiting.
  *
  ******************************************************************************/
@@ -152,7 +151,7 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout)
  * DESCRIPTION: Suspend running thread for specified amount of time.
  *              Note: ACPI specification requires that Stall() does not
  *              relinquish the processor, and delays longer than 100 usec
- *              should use Sleep() instead.  We allow stalls up to 255 usec
+ *              should use Sleep() instead. We allow stalls up to 255 usec
  *              for compatibility with other interpreters and existing BIOSs.
  *
  ******************************************************************************/
@@ -254,7 +253,7 @@ acpi_status acpi_ex_system_signal_event(union acpi_operand_object * obj_desc)
  * RETURN:      Status
  *
  * DESCRIPTION: Provides an access point to perform synchronization operations
- *              within the AML.  This operation is a request to wait for an
+ *              within the AML. This operation is a request to wait for an
  *              event.
  *
  ******************************************************************************/
index d1ab791..264d22d 100644 (file)
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: exutils - interpreter/scanner utilities
 /*
  * DEFINE_AML_GLOBALS is tested in amlcode.h
  * to determine whether certain global names should be "defined" or only
- * "declared" in the current compilation.  This enhances maintainability
+ * "declared" in the current compilation. This enhances maintainability
  * by enabling a single header file to embody all knowledge of the names
  * in question.
  *
  * Exactly one module of any executable should #define DEFINE_GLOBALS
- * before #including the header files which use this convention.  The
+ * before #including the header files which use this convention. The
  * names in question will be defined and initialized in that module,
  * and declared as extern in all other modules which #include those
  * header files.
index a1e71d0..90a9aea 100644 (file)
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface
@@ -136,7 +135,7 @@ acpi_status acpi_hw_set_mode(u32 mode)
  *
  * RETURN:      SYS_MODE_ACPI or SYS_MODE_LEGACY
  *
- * DESCRIPTION: Return current operating state of system.  Determined by
+ * DESCRIPTION: Return current operating state of system. Determined by
  *              querying the SCI_EN bit.
  *
  ******************************************************************************/
index db40765..6456004 100644 (file)
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: hwgpe - Low level GPE enable/disable/clear functions
@@ -339,7 +338,8 @@ acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 
 acpi_status
 acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
-                                struct acpi_gpe_block_info *gpe_block, void *context)
+                                struct acpi_gpe_block_info * gpe_block,
+                                void *context)
 {
        u32 i;
        acpi_status status;
index 1455ddc..65bc345 100644 (file)
@@ -259,7 +259,7 @@ acpi_hw_process_pci_list(struct acpi_pci_id *pci_id,
                status = acpi_hw_get_pci_device_info(pci_id, info->device,
                                                     &bus_number, &is_bridge);
                if (ACPI_FAILURE(status)) {
-                       return_ACPI_STATUS(status);
+                       return (status);
                }
 
                info = info->next;
@@ -271,7 +271,7 @@ acpi_hw_process_pci_list(struct acpi_pci_id *pci_id,
                          pci_id->segment, pci_id->bus, pci_id->device,
                          pci_id->function, status, bus_number, is_bridge));
 
-       return_ACPI_STATUS(AE_OK);
+       return (AE_OK);
 }
 
 /*******************************************************************************
index 4af6d20..f4e5750 100644 (file)
@@ -1,4 +1,3 @@
-
 /*******************************************************************************
  *
  * Module Name: hwregs - Read/write access functions for the various ACPI
index b6411f1..bfdce22 100644 (file)
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Name: hwtimer.c - ACPI Power Management Timer Interface
@@ -101,8 +100,7 @@ acpi_status acpi_get_timer(u32 * ticks)
                return_ACPI_STATUS(AE_BAD_PARAMETER);
        }
 
-       status =
-           acpi_hw_read(ticks, &acpi_gbl_FADT.xpm_timer_block);
+       status = acpi_hw_read(ticks, &acpi_gbl_FADT.xpm_timer_block);
 
        return_ACPI_STATUS(status);
 }
@@ -129,7 +127,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_timer)
  *              a versatile and accurate timer.
  *
  *              Note that this function accommodates only a single timer
- *              rollover.  Thus for 24-bit timers, this function should only
+ *              rollover. Thus for 24-bit timers, this function should only
  *              be used for calculating durations less than ~4.6 seconds
  *              (~20 minutes for 32-bit timers) -- calculations below:
  *
index c99d546..b6aae58 100644 (file)
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: hwvalid - I/O request validation
index 7bfd649..05a154c 100644 (file)
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Module Name: hwxface - Public ACPICA hardware interfaces
index 0ff1ece..ae443fe 100644 (file)
@@ -49,8 +49,7 @@
 ACPI_MODULE_NAME("hwxfsleep")
 
 /* Local prototypes */
-static acpi_status
-acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id);
+static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id);
 
 /*
  * Dispatch table used to efficiently branch to the various sleep
@@ -234,8 +233,7 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios)
  *              function.
  *
  ******************************************************************************/
-static acpi_status
-acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id)
+static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id)
 {
        acpi_status status;
        struct acpi_sleep_functions *sleep_functions =
@@ -369,8 +367,7 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
                return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
        }
 
-       status =
-           acpi_hw_sleep_dispatch(sleep_state, ACPI_SLEEP_FUNCTION_ID);
+       status = acpi_hw_sleep_dispatch(sleep_state, ACPI_SLEEP_FUNCTION_ID);
        return_ACPI_STATUS(status);
 }
 
@@ -396,8 +393,7 @@ acpi_status acpi_leave_sleep_state_prep(u8 sleep_state)
        ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep);
 
        status =
-           acpi_hw_sleep_dispatch(sleep_state,
-                                  ACPI_WAKE_PREP_FUNCTION_ID);
+           acpi_hw_sleep_dispatch(sleep_state, ACPI_WAKE_PREP_FUNCTION_ID);
        return_ACPI_STATUS(status);
 }
 
index 23db53c..d70eaf3 100644 (file)
@@ -110,11 +110,11 @@ acpi_status acpi_ns_root_initialize(void)
                status = acpi_ns_lookup(NULL, init_val->name, init_val->type,
                                        ACPI_IMODE_LOAD_PASS2,
                                        ACPI_NS_NO_UPSEARCH, NULL, &new_node);
-
-               if (ACPI_FAILURE(status) || (!new_node)) {      /* Must be on same line for code converter */
+               if (ACPI_FAILURE(status)) {
                        ACPI_EXCEPTION((AE_INFO, status,
                                        "Could not create predefined name %s",
                                        init_val->name));
+                       continue;
                }
 
                /*
@@ -179,8 +179,7 @@ acpi_status acpi_ns_root_initialize(void)
 
                                /* Build an object around the static string */
 
-                               obj_desc->string.length =
-                                   (u32) ACPI_STRLEN(val);
+                               obj_desc->string.length = (u32)ACPI_STRLEN(val);
                                obj_desc->string.pointer = val;
                                obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
                                break;
index ac389e5..15143c4 100644 (file)
@@ -332,7 +332,7 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node)
  *
  * RETURN:      None.
  *
- * DESCRIPTION: Delete a subtree of the namespace.  This includes all objects
+ * DESCRIPTION: Delete a subtree of the namespace. This includes all objects
  *              stored within the subtree.
  *
  ******************************************************************************/
@@ -418,7 +418,7 @@ void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_node)
  * RETURN:      Status
  *
  * DESCRIPTION: Delete entries within the namespace that are owned by a
- *              specific ID.  Used to delete entire ACPI tables.  All
+ *              specific ID. Used to delete entire ACPI tables. All
  *              reference counts are updated.
  *
  * MUTEX:       Locks namespace during deletion walk.
index 2526aaf..924b3c7 100644 (file)
@@ -209,14 +209,6 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
                                      "Invalid ACPI Object Type 0x%08X", type));
                }
 
-               if (!acpi_ut_valid_acpi_name(this_node->name.integer)) {
-                       this_node->name.integer =
-                           acpi_ut_repair_name(this_node->name.ascii);
-
-                       ACPI_WARNING((AE_INFO, "Invalid ACPI Name %08X",
-                                     this_node->name.integer));
-               }
-
                acpi_os_printf("%4.4s", acpi_ut_get_node_name(this_node));
        }
 
@@ -700,7 +692,7 @@ void acpi_ns_dump_entry(acpi_handle handle, u32 debug_level)
  *
  * PARAMETERS:  search_base         - Root of subtree to be dumped, or
  *                                    NS_ALL to dump the entire namespace
- *              max_depth           - Maximum depth of dump.  Use INT_MAX
+ *              max_depth           - Maximum depth of dump. Use INT_MAX
  *                                    for an effectively unlimited depth.
  *
  * RETURN:      None
index 95ffe8d..4328e2a 100644 (file)
@@ -96,8 +96,8 @@ acpi_status acpi_ns_initialize_objects(void)
        /* Walk entire namespace from the supplied root */
 
        status = acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
-                                    ACPI_UINT32_MAX, acpi_ns_init_one_object, NULL,
-                                    &info, NULL);
+                                    ACPI_UINT32_MAX, acpi_ns_init_one_object,
+                                    NULL, &info, NULL);
        if (ACPI_FAILURE(status)) {
                ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
        }
index 76935ff..911f991 100644 (file)
@@ -80,8 +80,8 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node)
 
        /*
         * Parse the table and load the namespace with all named
-        * objects found within.  Control methods are NOT parsed
-        * at this time.  In fact, the control methods cannot be
+        * objects found within. Control methods are NOT parsed
+        * at this time. In fact, the control methods cannot be
         * parsed until the entire namespace is loaded, because
         * if a control method makes a forward reference (call)
         * to another control method, we can't continue parsing
@@ -122,7 +122,7 @@ acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node)
        }
 
        /*
-        * Now we can parse the control methods.  We always parse
+        * Now we can parse the control methods. We always parse
         * them here for a sanity check, and if configured for
         * just-in-time parsing, we delete the control method
         * parse trees.
@@ -166,7 +166,7 @@ acpi_status acpi_ns_load_namespace(void)
        }
 
        /*
-        * Load the namespace.  The DSDT is required,
+        * Load the namespace. The DSDT is required,
         * but the SSDT and PSDT tables are optional.
         */
        status = acpi_ns_load_table_by_type(ACPI_TABLE_ID_DSDT);
@@ -283,7 +283,7 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle)
  *  RETURN:         Status
  *
  *  DESCRIPTION:    Shrinks the namespace, typically in response to an undocking
- *                  event.  Deletes an entire subtree starting from (and
+ *                  event. Deletes an entire subtree starting from (and
  *                  including) the given handle.
  *
  ******************************************************************************/
index 96e0eb6..55a175e 100644 (file)
@@ -195,7 +195,7 @@ acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node)
                        ACPI_ERROR((AE_INFO,
                                    "Invalid Namespace Node (%p) while traversing namespace",
                                    next_node));
-                       return 0;
+                       return (0);
                }
                size += ACPI_PATH_SEGMENT_LENGTH;
                next_node = next_node->parent;
index d6c9a3c..e69f7fa 100644 (file)
@@ -61,7 +61,7 @@ ACPI_MODULE_NAME("nsobject")
  * RETURN:      Status
  *
  * DESCRIPTION: Record the given object as the value associated with the
- *              name whose acpi_handle is passed.  If Object is NULL
+ *              name whose acpi_handle is passed. If Object is NULL
  *              and Type is ACPI_TYPE_ANY, set the name as having no value.
  *              Note: Future may require that the Node->Flags field be passed
  *              as a parameter.
@@ -133,7 +133,7 @@ acpi_ns_attach_object(struct acpi_namespace_node *node,
                 ((struct acpi_namespace_node *)object)->object) {
                /*
                 * Value passed is a name handle and that name has a
-                * non-null value.  Use that name's value and type.
+                * non-null value. Use that name's value and type.
                 */
                obj_desc = ((struct acpi_namespace_node *)object)->object;
                object_type = ((struct acpi_namespace_node *)object)->type;
@@ -321,7 +321,7 @@ union acpi_operand_object *acpi_ns_get_secondary_object(union
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Low-level attach data.  Create and attach a Data object.
+ * DESCRIPTION: Low-level attach data. Create and attach a Data object.
  *
  ******************************************************************************/
 
@@ -377,7 +377,7 @@ acpi_ns_attach_data(struct acpi_namespace_node *node,
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Low-level detach data.  Delete the data node, but the caller
+ * DESCRIPTION: Low-level detach data. Delete the data node, but the caller
  *              is responsible for the actual data.
  *
  ******************************************************************************/
index ec7ba2d..233f756 100644 (file)
@@ -168,11 +168,11 @@ acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node)
        /*
         * AML Parse, pass 1
         *
-        * In this pass, we load most of the namespace.  Control methods
-        * are not parsed until later.  A parse tree is not created.  Instead,
-        * each Parser Op subtree is deleted when it is finished.  This saves
+        * In this pass, we load most of the namespace. Control methods
+        * are not parsed until later. A parse tree is not created. Instead,
+        * each Parser Op subtree is deleted when it is finished. This saves
         * a great deal of memory, and allows a small cache of parse objects
-        * to service the entire parse.  The second pass of the parse then
+        * to service the entire parse. The second pass of the parse then
         * performs another complete parse of the AML.
         */
        ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n"));
index 456cc85..1d2d8ff 100644 (file)
@@ -314,22 +314,7 @@ acpi_ns_search_and_enter(u32 target_name,
         * this problem, and we want to be able to enable ACPI support for them,
         * even though there are a few bad names.
         */
-       if (!acpi_ut_valid_acpi_name(target_name)) {
-               target_name =
-                   acpi_ut_repair_name(ACPI_CAST_PTR(char, &target_name));
-
-               /* Report warning only if in strict mode or debug mode */
-
-               if (!acpi_gbl_enable_interpreter_slack) {
-                       ACPI_WARNING((AE_INFO,
-                                     "Found bad character(s) in name, repaired: [%4.4s]\n",
-                                     ACPI_CAST_PTR(char, &target_name)));
-               } else {
-                       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                         "Found bad character(s) in name, repaired: [%4.4s]\n",
-                                         ACPI_CAST_PTR(char, &target_name)));
-               }
-       }
+       acpi_ut_repair_name(ACPI_CAST_PTR(char, &target_name));
 
        /* Try to find the name in the namespace level specified by the caller */
 
index ef753a4..b5b4cb7 100644 (file)
@@ -530,7 +530,7 @@ acpi_ns_externalize_name(u32 internal_name_length,
            ((num_segments > 0) ? (num_segments - 1) : 0) + 1;
 
        /*
-        * Check to see if we're still in bounds.  If not, there's a problem
+        * Check to see if we're still in bounds. If not, there's a problem
         * with internal_name (invalid format).
         */
        if (required_length > internal_name_length) {
@@ -557,10 +557,14 @@ acpi_ns_externalize_name(u32 internal_name_length,
                                (*converted_name)[j++] = '.';
                        }
 
-                       (*converted_name)[j++] = internal_name[names_index++];
-                       (*converted_name)[j++] = internal_name[names_index++];
-                       (*converted_name)[j++] = internal_name[names_index++];
-                       (*converted_name)[j++] = internal_name[names_index++];
+                       /* Copy and validate the 4-char name segment */
+
+                       ACPI_MOVE_NAME(&(*converted_name)[j],
+                                      &internal_name[names_index]);
+                       acpi_ut_repair_name(&(*converted_name)[j]);
+
+                       j += ACPI_NAME_SIZE;
+                       names_index += ACPI_NAME_SIZE;
                }
        }
 
@@ -681,7 +685,7 @@ u32 acpi_ns_opens_scope(acpi_object_type type)
  *                            \ (backslash) and ^ (carat) prefixes, and the
  *                            . (period) to separate segments are supported.
  *              prefix_node  - Root of subtree to be searched, or NS_ALL for the
- *                            root of the name space.  If Name is fully
+ *                            root of the name space. If Name is fully
  *                            qualified (first s8 is '\'), the passed value
  *                            of Scope will not be accessed.
  *              flags       - Used to indicate whether to perform upsearch or
@@ -689,7 +693,7 @@ u32 acpi_ns_opens_scope(acpi_object_type type)
  *              return_node - Where the Node is returned
  *
  * DESCRIPTION: Look up a name relative to a given scope and return the
- *              corresponding Node.  NOTE: Scope can be null.
+ *              corresponding Node. NOTE: Scope can be null.
  *
  * MUTEX:       Locks namespace
  *
index 730bccc..0483877 100644 (file)
@@ -60,8 +60,8 @@ ACPI_MODULE_NAME("nswalk")
  * RETURN:      struct acpi_namespace_node - Pointer to the NEXT child or NULL if
  *                                    none is found.
  *
- * DESCRIPTION: Return the next peer node within the namespace.  If Handle
- *              is valid, Scope is ignored.  Otherwise, the first node
+ * DESCRIPTION: Return the next peer node within the namespace. If Handle
+ *              is valid, Scope is ignored. Otherwise, the first node
  *              within Scope is returned.
  *
  ******************************************************************************/
@@ -97,8 +97,8 @@ struct acpi_namespace_node *acpi_ns_get_next_node(struct acpi_namespace_node
  * RETURN:      struct acpi_namespace_node - Pointer to the NEXT child or NULL if
  *                                    none is found.
  *
- * DESCRIPTION: Return the next peer node within the namespace.  If Handle
- *              is valid, Scope is ignored.  Otherwise, the first node
+ * DESCRIPTION: Return the next peer node within the namespace. If Handle
+ *              is valid, Scope is ignored. Otherwise, the first node
  *              within Scope is returned.
  *
  ******************************************************************************/
@@ -305,7 +305,7 @@ acpi_ns_walk_namespace(acpi_object_type type,
 
                /*
                 * Depth first search: Attempt to go down another level in the
-                * namespace if we are allowed to.  Don't go any further if we have
+                * namespace if we are allowed to. Don't go any further if we have
                 * reached the caller specified maximum depth or if the user
                 * function has specified that the maximum depth has been reached.
                 */
index 9692e67..d6a9f77 100644 (file)
@@ -61,16 +61,16 @@ static void acpi_ns_resolve_references(struct acpi_evaluate_info *info);
  * PARAMETERS:  handle              - Object handle (optional)
  *              pathname            - Object pathname (optional)
  *              external_params     - List of parameters to pass to method,
- *                                    terminated by NULL.  May be NULL
+ *                                    terminated by NULL. May be NULL
  *                                    if no parameters are being passed.
  *              return_buffer       - Where to put method's return value (if
- *                                    any).  If NULL, no value is returned.
+ *                                    any). If NULL, no value is returned.
  *              return_type         - Expected type of return object
  *
  * RETURN:      Status
  *
  * DESCRIPTION: Find and evaluate the given object, passing the given
- *              parameters if necessary.  One of "Handle" or "Pathname" must
+ *              parameters if necessary. One of "Handle" or "Pathname" must
  *              be valid (non-null)
  *
  ******************************************************************************/
@@ -155,15 +155,15 @@ ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed)
  * PARAMETERS:  handle              - Object handle (optional)
  *              pathname            - Object pathname (optional)
  *              external_params     - List of parameters to pass to method,
- *                                    terminated by NULL.  May be NULL
+ *                                    terminated by NULL. May be NULL
  *                                    if no parameters are being passed.
  *              return_buffer       - Where to put method's return value (if
- *                                    any).  If NULL, no value is returned.
+ *                                    any). If NULL, no value is returned.
  *
  * RETURN:      Status
  *
  * DESCRIPTION: Find and evaluate the given object, passing the given
- *              parameters if necessary.  One of "Handle" or "Pathname" must
+ *              parameters if necessary. One of "Handle" or "Pathname" must
  *              be valid (non-null)
  *
  ******************************************************************************/
@@ -542,15 +542,15 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
        acpi_status status;
        struct acpi_namespace_node *node;
        u32 flags;
-       struct acpica_device_id *hid;
-       struct acpica_device_id_list *cid;
+       struct acpi_pnp_device_id *hid;
+       struct acpi_pnp_device_id_list *cid;
        u32 i;
        u8 found;
        int no_match;
 
        status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
        if (ACPI_FAILURE(status)) {
-               return (status);
+               return_ACPI_STATUS(status);
        }
 
        node = acpi_ns_validate_handle(obj_handle);
@@ -656,7 +656,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
  * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
  *              starting (and ending) at the object specified by start_handle.
  *              The user_function is called whenever an object of type
- *              Device is found.  If the user function returns
+ *              Device is found. If the user function returns
  *              a non-zero value, the search is terminated immediately and this
  *              value is returned to the caller.
  *
index 08e9610..811c6f1 100644 (file)
@@ -53,8 +53,8 @@
 ACPI_MODULE_NAME("nsxfname")
 
 /* Local prototypes */
-static char *acpi_ns_copy_device_id(struct acpica_device_id *dest,
-                                   struct acpica_device_id *source,
+static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest,
+                                   struct acpi_pnp_device_id *source,
                                    char *string_area);
 
 /******************************************************************************
@@ -69,8 +69,8 @@ static char *acpi_ns_copy_device_id(struct acpica_device_id *dest,
  * RETURN:      Status
  *
  * DESCRIPTION: This routine will search for a caller specified name in the
- *              name space.  The caller can restrict the search region by
- *              specifying a non NULL parent.  The parent value is itself a
+ *              name space. The caller can restrict the search region by
+ *              specifying a non NULL parent. The parent value is itself a
  *              namespace handle.
  *
  ******************************************************************************/
@@ -149,7 +149,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_handle)
  * RETURN:      Pointer to a string containing the fully qualified Name.
  *
  * DESCRIPTION: This routine returns the fully qualified name associated with
- *              the Handle parameter.  This and the acpi_pathname_to_handle are
+ *              the Handle parameter. This and the acpi_pathname_to_handle are
  *              complementary functions.
  *
  ******************************************************************************/
@@ -202,8 +202,7 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer)
 
        /* Just copy the ACPI name from the Node and zero terminate it */
 
-       ACPI_STRNCPY(buffer->pointer, acpi_ut_get_node_name(node),
-                    ACPI_NAME_SIZE);
+       ACPI_MOVE_NAME(buffer->pointer, acpi_ut_get_node_name(node));
        ((char *)buffer->pointer)[ACPI_NAME_SIZE] = 0;
        status = AE_OK;
 
@@ -219,20 +218,21 @@ ACPI_EXPORT_SYMBOL(acpi_get_name)
  *
  * FUNCTION:    acpi_ns_copy_device_id
  *
- * PARAMETERS:  dest                - Pointer to the destination DEVICE_ID
- *              source              - Pointer to the source DEVICE_ID
+ * PARAMETERS:  dest                - Pointer to the destination PNP_DEVICE_ID
+ *              source              - Pointer to the source PNP_DEVICE_ID
  *              string_area         - Pointer to where to copy the dest string
  *
  * RETURN:      Pointer to the next string area
  *
- * DESCRIPTION: Copy a single DEVICE_ID, including the string data.
+ * DESCRIPTION: Copy a single PNP_DEVICE_ID, including the string data.
  *
  ******************************************************************************/
-static char *acpi_ns_copy_device_id(struct acpica_device_id *dest,
-                                   struct acpica_device_id *source,
+static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest,
+                                   struct acpi_pnp_device_id *source,
                                    char *string_area)
 {
-       /* Create the destination DEVICE_ID */
+
+       /* Create the destination PNP_DEVICE_ID */
 
        dest->string = string_area;
        dest->length = source->length;
@@ -256,8 +256,8 @@ static char *acpi_ns_copy_device_id(struct acpica_device_id *dest,
  *              namespace node and possibly by running several standard
  *              control methods (Such as in the case of a device.)
  *
- * For Device and Processor objects, run the Device _HID, _UID, _CID, _STA,
- * _ADR, _sx_w, and _sx_d methods.
+ * For Device and Processor objects, run the Device _HID, _UID, _CID, _SUB,
+ * _STA, _ADR, _sx_w, and _sx_d methods.
  *
  * Note: Allocates the return buffer, must be freed by the caller.
  *
@@ -269,9 +269,10 @@ acpi_get_object_info(acpi_handle handle,
 {
        struct acpi_namespace_node *node;
        struct acpi_device_info *info;
-       struct acpica_device_id_list *cid_list = NULL;
-       struct acpica_device_id *hid = NULL;
-       struct acpica_device_id *uid = NULL;
+       struct acpi_pnp_device_id_list *cid_list = NULL;
+       struct acpi_pnp_device_id *hid = NULL;
+       struct acpi_pnp_device_id *uid = NULL;
+       struct acpi_pnp_device_id *sub = NULL;
        char *next_id_string;
        acpi_object_type type;
        acpi_name name;
@@ -316,7 +317,7 @@ acpi_get_object_info(acpi_handle handle,
        if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) {
                /*
                 * Get extra info for ACPI Device/Processor objects only:
-                * Run the Device _HID, _UID, and _CID methods.
+                * Run the Device _HID, _UID, _SUB, and _CID methods.
                 *
                 * Note: none of these methods are required, so they may or may
                 * not be present for this device. The Info->Valid bitfield is used
@@ -339,6 +340,14 @@ acpi_get_object_info(acpi_handle handle,
                        valid |= ACPI_VALID_UID;
                }
 
+               /* Execute the Device._SUB method */
+
+               status = acpi_ut_execute_SUB(node, &sub);
+               if (ACPI_SUCCESS(status)) {
+                       info_size += sub->length;
+                       valid |= ACPI_VALID_SUB;
+               }
+
                /* Execute the Device._CID method */
 
                status = acpi_ut_execute_CID(node, &cid_list);
@@ -348,7 +357,7 @@ acpi_get_object_info(acpi_handle handle,
 
                        info_size +=
                            (cid_list->list_size -
-                            sizeof(struct acpica_device_id_list));
+                            sizeof(struct acpi_pnp_device_id_list));
                        valid |= ACPI_VALID_CID;
                }
        }
@@ -418,16 +427,17 @@ acpi_get_object_info(acpi_handle handle,
        next_id_string = ACPI_CAST_PTR(char, info->compatible_id_list.ids);
        if (cid_list) {
 
-               /* Point past the CID DEVICE_ID array */
+               /* Point past the CID PNP_DEVICE_ID array */
 
                next_id_string +=
                    ((acpi_size) cid_list->count *
-                    sizeof(struct acpica_device_id));
+                    sizeof(struct acpi_pnp_device_id));
        }
 
        /*
-        * Copy the HID, UID, and CIDs to the return buffer. The variable-length
-        * strings are copied to the reserved area at the end of the buffer.
+        * Copy the HID, UID, SUB, and CIDs to the return buffer.
+        * The variable-length strings are copied to the reserved area
+        * at the end of the buffer.
         *
         * For HID and CID, check if the ID is a PCI Root Bridge.
         */
@@ -445,6 +455,11 @@ acpi_get_object_info(acpi_handle handle,
                                                        uid, next_id_string);
        }
 
+       if (sub) {
+               next_id_string = acpi_ns_copy_device_id(&info->subsystem_id,
+                                                       sub, next_id_string);
+       }
+
        if (cid_list) {
                info->compatible_id_list.count = cid_list->count;
                info->compatible_id_list.list_size = cid_list->list_size;
@@ -481,6 +496,9 @@ acpi_get_object_info(acpi_handle handle,
        if (uid) {
                ACPI_FREE(uid);
        }
+       if (sub) {
+               ACPI_FREE(sub);
+       }
        if (cid_list) {
                ACPI_FREE(cid_list);
        }
index 6766fc4..9d029da 100644 (file)
@@ -220,8 +220,8 @@ ACPI_EXPORT_SYMBOL(acpi_get_parent)
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Return the next peer object within the namespace.  If Handle is
- *              valid, Scope is ignored.  Otherwise, the first object within
+ * DESCRIPTION: Return the next peer object within the namespace. If Handle is
+ *              valid, Scope is ignored. Otherwise, the first object within
  *              Scope is returned.
  *
  ******************************************************************************/
index 844464c..cb79e2d 100644 (file)
@@ -120,7 +120,7 @@ acpi_ps_get_next_package_length(struct acpi_parse_state *parser_state)
  * RETURN:      Pointer to end-of-package +1
  *
  * DESCRIPTION: Get next package length and return a pointer past the end of
- *              the package.  Consumes the package length field
+ *              the package. Consumes the package length field
  *
  ******************************************************************************/
 
@@ -147,8 +147,8 @@ u8 *acpi_ps_get_next_package_end(struct acpi_parse_state *parser_state)
  * RETURN:      Pointer to the start of the name string (pointer points into
  *              the AML.
  *
- * DESCRIPTION: Get next raw namestring within the AML stream.  Handles all name
- *              prefix characters.  Set parser state to point past the string.
+ * DESCRIPTION: Get next raw namestring within the AML stream. Handles all name
+ *              prefix characters. Set parser state to point past the string.
  *              (Name is consumed from the AML.)
  *
  ******************************************************************************/
@@ -220,7 +220,7 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state)
  *
  * DESCRIPTION: Get next name (if method call, return # of required args).
  *              Names are looked up in the internal namespace to determine
- *              if the name represents a control method.  If a method
+ *              if the name represents a control method. If a method
  *              is found, the number of arguments to the method is returned.
  *              This information is critical for parsing to continue correctly.
  *
index 799162c..5607805 100644 (file)
@@ -133,18 +133,46 @@ static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state)
 
        case AML_CLASS_UNKNOWN:
 
-               /* The opcode is unrecognized. Just skip unknown opcodes */
+               /* The opcode is unrecognized. Complain and skip unknown opcodes */
 
-               ACPI_ERROR((AE_INFO,
-                           "Found unknown opcode 0x%X at AML address %p offset 0x%X, ignoring",
-                           walk_state->opcode, walk_state->parser_state.aml,
-                           walk_state->aml_offset));
+               if (walk_state->pass_number == 2) {
+                       ACPI_ERROR((AE_INFO,
+                                   "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring",
+                                   walk_state->opcode,
+                                   (u32)(walk_state->aml_offset +
+                                         sizeof(struct acpi_table_header))));
 
-               ACPI_DUMP_BUFFER(walk_state->parser_state.aml, 128);
+                       ACPI_DUMP_BUFFER(walk_state->parser_state.aml - 16, 48);
 
-               /* Assume one-byte bad opcode */
+#ifdef ACPI_ASL_COMPILER
+                       /*
+                        * This is executed for the disassembler only. Output goes
+                        * to the disassembled ASL output file.
+                        */
+                       acpi_os_printf
+                           ("/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n",
+                            walk_state->opcode,
+                            (u32)(walk_state->aml_offset +
+                                  sizeof(struct acpi_table_header)));
+
+                       /* Dump the context surrounding the invalid opcode */
+
+                       acpi_ut_dump_buffer(((u8 *)walk_state->parser_state.
+                                            aml - 16), 48, DB_BYTE_DISPLAY,
+                                           walk_state->aml_offset +
+                                           sizeof(struct acpi_table_header) -
+                                           16);
+                       acpi_os_printf(" */\n");
+#endif
+               }
+
+               /* Increment past one-byte or two-byte opcode */
 
                walk_state->parser_state.aml++;
+               if (walk_state->opcode > 0xFF) {        /* Can only happen if first byte is 0x5B */
+                       walk_state->parser_state.aml++;
+               }
+
                return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE);
 
        default:
@@ -519,11 +547,18 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
                                        if ((op_info->class ==
                                             AML_CLASS_EXECUTE) && (!arg)) {
                                                ACPI_WARNING((AE_INFO,
-                                                             "Detected an unsupported executable opcode "
-                                                             "at module-level: [0x%.4X] at table offset 0x%.4X",
-                                                             op->common.aml_opcode,
-                                                             (u32)((aml_op_start - walk_state->parser_state.aml_start)
-                                                               + sizeof(struct acpi_table_header))));
+                                                             "Unsupported module-level executable opcode "
+                                                             "0x%.2X at table offset 0x%.4X",
+                                                             op->common.
+                                                             aml_opcode,
+                                                             (u32)
+                                                             (ACPI_PTR_DIFF
+                                                              (aml_op_start,
+                                                               walk_state->
+                                                               parser_state.
+                                                               aml_start) +
+                                                              sizeof(struct
+                                                                     acpi_table_header))));
                                        }
                                }
                                break;
@@ -843,8 +878,6 @@ acpi_ps_complete_op(struct acpi_walk_state *walk_state,
                *op = NULL;
        }
 
-       ACPI_PREEMPTION_POINT();
-
        return_ACPI_STATUS(AE_OK);
 }
 
index ed1d457..1793d93 100644 (file)
@@ -59,7 +59,7 @@ static const u8 acpi_gbl_argument_count[] =
  *
  * DESCRIPTION: Opcode table. Each entry contains <opcode, type, name, operands>
  *              The name is a simple ascii string, the operand specifier is an
- *              ascii string with one letter per operand.  The letter specifies
+ *              ascii string with one letter per operand. The letter specifies
  *              the operand type.
  *
  ******************************************************************************/
@@ -183,7 +183,7 @@ static const u8 acpi_gbl_argument_count[] =
  ******************************************************************************/
 
 /*
- * Master Opcode information table.  A summary of everything we know about each
+ * Master Opcode information table. A summary of everything we know about each
  * opcode, all in one place.
  */
 const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
@@ -392,10 +392,12 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
                 AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
 /* 38 */ ACPI_OP("LAnd", ARGP_LAND_OP, ARGI_LAND_OP, ACPI_TYPE_ANY,
                 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
-                AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT),
+                        AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC |
+                        AML_CONSTANT),
 /* 39 */ ACPI_OP("LOr", ARGP_LOR_OP, ARGI_LOR_OP, ACPI_TYPE_ANY,
                 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
-                AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT),
+                        AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC |
+                        AML_CONSTANT),
 /* 3A */ ACPI_OP("LNot", ARGP_LNOT_OP, ARGI_LNOT_OP, ACPI_TYPE_ANY,
                 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R,
                 AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
@@ -495,7 +497,8 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
                 AML_NSNODE | AML_NAMED | AML_DEFER),
 /* 59 */ ACPI_OP("Field", ARGP_FIELD_OP, ARGI_FIELD_OP, ACPI_TYPE_ANY,
                 AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD,
-                AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD),
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+                        AML_FIELD),
 /* 5A */ ACPI_OP("Device", ARGP_DEVICE_OP, ARGI_DEVICE_OP,
                 ACPI_TYPE_DEVICE, AML_CLASS_NAMED_OBJECT,
                 AML_TYPE_NAMED_NO_OBJ,
@@ -519,12 +522,13 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
 /* 5E */ ACPI_OP("IndexField", ARGP_INDEX_FIELD_OP, ARGI_INDEX_FIELD_OP,
                 ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
                 AML_TYPE_NAMED_FIELD,
-                AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD),
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+                        AML_FIELD),
 /* 5F */ ACPI_OP("BankField", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP,
-                ACPI_TYPE_LOCAL_BANK_FIELD, AML_CLASS_NAMED_OBJECT,
-                AML_TYPE_NAMED_FIELD,
-                AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD |
-                AML_DEFER),
+                        ACPI_TYPE_LOCAL_BANK_FIELD,
+                        AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD,
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+                        AML_FIELD | AML_DEFER),
 
 /* Internal opcodes that map to invalid AML opcodes */
 
@@ -632,7 +636,8 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
 /* 7D */ ACPI_OP("[EvalSubTree]", ARGP_SCOPE_OP, ARGI_SCOPE_OP,
                 ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
                 AML_TYPE_NAMED_NO_OBJ,
-                AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE),
+                        AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+                        AML_NSNODE),
 
 /* ACPI 3.0 opcodes */
 
@@ -695,7 +700,7 @@ static const u8 acpi_gbl_short_op_index[256] = {
 
 /*
  * This table is indexed by the second opcode of the extended opcode
- * pair.  It returns an index into the opcode table (acpi_gbl_aml_op_info)
+ * pair. It returns an index into the opcode table (acpi_gbl_aml_op_info)
  */
 static const u8 acpi_gbl_long_op_index[NUM_EXTENDED_OPCODE] = {
 /*              0     1     2     3     4     5     6     7  */
index 0198570..2494caf 100644 (file)
@@ -43,9 +43,9 @@
 
 /*
  * Parse the AML and build an operation tree as most interpreters,
- * like Perl, do.  Parsing is done by hand rather than with a YACC
+ * like Perl, do. Parsing is done by hand rather than with a YACC
  * generated parser to tightly constrain stack and dynamic memory
- * usage.  At the same time, parsing is kept flexible and the code
+ * usage. At the same time, parsing is kept flexible and the code
  * fairly compact by parsing based on a list of AML opcode
  * templates in aml_op_info[]
  */
@@ -379,7 +379,7 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state,
        case AE_CTRL_FALSE:
                /*
                 * Either an IF/WHILE Predicate was false or we encountered a BREAK
-                * opcode.  In both cases, we do not execute the rest of the
+                * opcode. In both cases, we do not execute the rest of the
                 * package;  We simply close out the parent (finishing the walk of
                 * this branch of the tree) and continue execution at the parent
                 * level.
@@ -459,8 +459,9 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
 
                        /* Executing a control method - additional cleanup */
 
-                       acpi_ds_terminate_control_method(
-                               walk_state->method_desc, walk_state);
+                       acpi_ds_terminate_control_method(walk_state->
+                                                        method_desc,
+                                                        walk_state);
                }
 
                acpi_ds_delete_walk_state(walk_state);
@@ -487,7 +488,7 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state)
        acpi_gbl_current_walk_list = thread;
 
        /*
-        * Execute the walk loop as long as there is a valid Walk State.  This
+        * Execute the walk loop as long as there is a valid Walk State. This
         * handles nested control method invocations without recursion.
         */
        ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "State=%p\n", walk_state));
index 8736ad5..4137dcb 100644 (file)
@@ -108,7 +108,7 @@ void acpi_ps_init_op(union acpi_parse_object *op, u16 opcode)
  * RETURN:      Pointer to the new Op, null on failure
  *
  * DESCRIPTION: Allocate an acpi_op, choose op type (and thus size) based on
- *              opcode.  A cache of opcodes is available for the pure
+ *              opcode. A cache of opcodes is available for the pure
  *              GENERIC_OP, since this is by far the most commonly used.
  *
  ******************************************************************************/
@@ -164,7 +164,7 @@ union acpi_parse_object *acpi_ps_alloc_op(u16 opcode)
  *
  * RETURN:      None.
  *
- * DESCRIPTION: Free an Op object.  Either put it on the GENERIC_OP cache list
+ * DESCRIPTION: Free an Op object. Either put it on the GENERIC_OP cache list
  *              or actually free it.
  *
  ******************************************************************************/
index de12469..147feb6 100644 (file)
@@ -457,6 +457,15 @@ acpi_rs_get_list_length(u8 * aml_buffer,
                         * Get the number of vendor data bytes
                         */
                        extra_struct_bytes = resource_length;
+
+                       /*
+                        * There is already one byte included in the minimum
+                        * descriptor size. If there are extra struct bytes,
+                        * subtract one from the count.
+                        */
+                       if (extra_struct_bytes) {
+                               extra_struct_bytes--;
+                       }
                        break;
 
                case ACPI_RESOURCE_NAME_END_TAG:
@@ -601,7 +610,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
        /*
         * Calculate the size of the return buffer.
         * The base size is the number of elements * the sizes of the
-        * structures.  Additional space for the strings is added below.
+        * structures. Additional space for the strings is added below.
         * The minus one is to subtract the size of the u8 Source[1]
         * member because it is added below.
         *
@@ -664,8 +673,7 @@ acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
                                                     (*sub_object_list)->string.
                                                     length + 1);
                        } else {
-                               temp_size_needed +=
-                                   acpi_ns_get_pathname_length((*sub_object_list)->reference.node);
+                               temp_size_needed += acpi_ns_get_pathname_length((*sub_object_list)->reference.node);
                        }
                } else {
                        /*
index 46b5324..8b64db9 100644 (file)
@@ -109,7 +109,7 @@ acpi_rs_convert_aml_to_resources(u8 * aml,
                ACPI_ERROR((AE_INFO,
                            "Invalid/unsupported resource descriptor: Type 0x%2.2X",
                            resource_index));
-               return (AE_AML_INVALID_RESOURCE_TYPE);
+               return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
        }
 
        /* Convert the AML byte stream resource to a local resource struct */
@@ -200,7 +200,7 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,
                        ACPI_ERROR((AE_INFO,
                                    "Invalid/unsupported resource descriptor: Type 0x%2.2X",
                                    resource->type));
-                       return (AE_AML_INVALID_RESOURCE_TYPE);
+                       return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
                }
 
                status = acpi_rs_convert_resource_to_aml(resource,
index 57deae1..77d1db2 100644 (file)
@@ -77,7 +77,7 @@ acpi_tb_find_table(char *signature,
        /* Normalize the input strings */
 
        ACPI_MEMSET(&header, 0, sizeof(struct acpi_table_header));
-       ACPI_STRNCPY(header.signature, signature, ACPI_NAME_SIZE);
+       ACPI_MOVE_NAME(header.signature, signature);
        ACPI_STRNCPY(header.oem_id, oem_id, ACPI_OEM_ID_SIZE);
        ACPI_STRNCPY(header.oem_table_id, oem_table_id, ACPI_OEM_TABLE_ID_SIZE);
 
index 70f9d78..f540ae4 100644 (file)
@@ -526,6 +526,8 @@ void acpi_tb_terminate(void)
 
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
        (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+
+       return_VOID;
 }
 
 /*******************************************************************************
index b6cea30..285e24b 100644 (file)
@@ -354,7 +354,7 @@ u8 acpi_tb_checksum(u8 *buffer, u32 length)
                sum = (u8) (sum + *(buffer++));
        }
 
-       return sum;
+       return (sum);
 }
 
 /*******************************************************************************
index 2110126..f563278 100644 (file)
@@ -236,7 +236,7 @@ acpi_get_table_header(char *signature,
                                                       sizeof(struct
                                                              acpi_table_header));
                                if (!header) {
-                                       return AE_NO_MEMORY;
+                                       return (AE_NO_MEMORY);
                                }
                                ACPI_MEMCPY(out_table_header, header,
                                            sizeof(struct acpi_table_header));
@@ -244,7 +244,7 @@ acpi_get_table_header(char *signature,
                                                     sizeof(struct
                                                            acpi_table_header));
                        } else {
-                               return AE_NOT_FOUND;
+                               return (AE_NOT_FOUND);
                        }
                } else {
                        ACPI_MEMCPY(out_table_header,
index f87cc63..a5e1e4e 100644 (file)
@@ -211,7 +211,7 @@ static acpi_status acpi_tb_load_namespace(void)
  * DESCRIPTION: Dynamically load an ACPI table from the caller's buffer. Must
  *              be a valid ACPI table with a valid ACPI table header.
  *              Note1: Mainly intended to support hotplug addition of SSDTs.
- *              Note2: Does not copy the incoming table. User is reponsible
+ *              Note2: Does not copy the incoming table. User is responsible
  *              to ensure that the table is not deleted or unmapped.
  *
  ******************************************************************************/
index 74e7208..28f3302 100644 (file)
@@ -67,7 +67,6 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp);
 
 static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
 {
-       ACPI_FUNCTION_ENTRY();
 
        /*
         * The signature and checksum must both be correct
@@ -108,7 +107,7 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
  * RETURN:      Status, RSDP physical address
  *
  * DESCRIPTION: Search lower 1Mbyte of memory for the root system descriptor
- *              pointer structure.  If it is found, set *RSDP to point to it.
+ *              pointer structure. If it is found, set *RSDP to point to it.
  *
  * NOTE1:       The RSDP must be either in the first 1K of the Extended
  *              BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.)
diff --git a/drivers/acpi/acpica/utcache.c b/drivers/acpi/acpica/utcache.c
new file mode 100644 (file)
index 0000000..e1d40ed
--- /dev/null
@@ -0,0 +1,323 @@
+/******************************************************************************
+ *
+ * Module Name: utcache - local cache allocation routines
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+
+#define _COMPONENT          ACPI_UTILITIES
+ACPI_MODULE_NAME("utcache")
+
+#ifdef ACPI_USE_LOCAL_CACHE
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_os_create_cache
+ *
+ * PARAMETERS:  cache_name      - Ascii name for the cache
+ *              object_size     - Size of each cached object
+ *              max_depth       - Maximum depth of the cache (in objects)
+ *              return_cache    - Where the new cache object is returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Create a cache object
+ *
+ ******************************************************************************/
+acpi_status
+acpi_os_create_cache(char *cache_name,
+                    u16 object_size,
+                    u16 max_depth, struct acpi_memory_list ** return_cache)
+{
+       struct acpi_memory_list *cache;
+
+       ACPI_FUNCTION_ENTRY();
+
+       if (!cache_name || !return_cache || (object_size < 16)) {
+               return (AE_BAD_PARAMETER);
+       }
+
+       /* Create the cache object */
+
+       cache = acpi_os_allocate(sizeof(struct acpi_memory_list));
+       if (!cache) {
+               return (AE_NO_MEMORY);
+       }
+
+       /* Populate the cache object and return it */
+
+       ACPI_MEMSET(cache, 0, sizeof(struct acpi_memory_list));
+       cache->link_offset = 8;
+       cache->list_name = cache_name;
+       cache->object_size = object_size;
+       cache->max_depth = max_depth;
+
+       *return_cache = cache;
+       return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_os_purge_cache
+ *
+ * PARAMETERS:  cache           - Handle to cache object
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Free all objects within the requested cache.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_os_purge_cache(struct acpi_memory_list * cache)
+{
+       char *next;
+       acpi_status status;
+
+       ACPI_FUNCTION_ENTRY();
+
+       if (!cache) {
+               return (AE_BAD_PARAMETER);
+       }
+
+       status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
+       if (ACPI_FAILURE(status)) {
+               return (status);
+       }
+
+       /* Walk the list of objects in this cache */
+
+       while (cache->list_head) {
+
+               /* Delete and unlink one cached state object */
+
+               next = *(ACPI_CAST_INDIRECT_PTR(char,
+                                               &(((char *)cache->
+                                                  list_head)[cache->
+                                                             link_offset])));
+               ACPI_FREE(cache->list_head);
+
+               cache->list_head = next;
+               cache->current_depth--;
+       }
+
+       (void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
+       return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_os_delete_cache
+ *
+ * PARAMETERS:  cache           - Handle to cache object
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Free all objects within the requested cache and delete the
+ *              cache object.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_os_delete_cache(struct acpi_memory_list * cache)
+{
+       acpi_status status;
+
+       ACPI_FUNCTION_ENTRY();
+
+       /* Purge all objects in the cache */
+
+       status = acpi_os_purge_cache(cache);
+       if (ACPI_FAILURE(status)) {
+               return (status);
+       }
+
+       /* Now we can delete the cache object */
+
+       acpi_os_free(cache);
+       return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_os_release_object
+ *
+ * PARAMETERS:  cache       - Handle to cache object
+ *              object      - The object to be released
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Release an object to the specified cache. If cache is full,
+ *              the object is deleted.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_os_release_object(struct acpi_memory_list * cache, void *object)
+{
+       acpi_status status;
+
+       ACPI_FUNCTION_ENTRY();
+
+       if (!cache || !object) {
+               return (AE_BAD_PARAMETER);
+       }
+
+       /* If cache is full, just free this object */
+
+       if (cache->current_depth >= cache->max_depth) {
+               ACPI_FREE(object);
+               ACPI_MEM_TRACKING(cache->total_freed++);
+       }
+
+       /* Otherwise put this object back into the cache */
+
+       else {
+               status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
+               if (ACPI_FAILURE(status)) {
+                       return (status);
+               }
+
+               /* Mark the object as cached */
+
+               ACPI_MEMSET(object, 0xCA, cache->object_size);
+               ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_CACHED);
+
+               /* Put the object at the head of the cache list */
+
+               *(ACPI_CAST_INDIRECT_PTR(char,
+                                        &(((char *)object)[cache->
+                                                           link_offset]))) =
+                   cache->list_head;
+               cache->list_head = object;
+               cache->current_depth++;
+
+               (void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
+       }
+
+       return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_os_acquire_object
+ *
+ * PARAMETERS:  cache           - Handle to cache object
+ *
+ * RETURN:      the acquired object. NULL on error
+ *
+ * DESCRIPTION: Get an object from the specified cache. If cache is empty,
+ *              the object is allocated.
+ *
+ ******************************************************************************/
+
+void *acpi_os_acquire_object(struct acpi_memory_list *cache)
+{
+       acpi_status status;
+       void *object;
+
+       ACPI_FUNCTION_NAME(os_acquire_object);
+
+       if (!cache) {
+               return (NULL);
+       }
+
+       status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
+       if (ACPI_FAILURE(status)) {
+               return (NULL);
+       }
+
+       ACPI_MEM_TRACKING(cache->requests++);
+
+       /* Check the cache first */
+
+       if (cache->list_head) {
+
+               /* There is an object available, use it */
+
+               object = cache->list_head;
+               cache->list_head = *(ACPI_CAST_INDIRECT_PTR(char,
+                                                           &(((char *)
+                                                              object)[cache->
+                                                                      link_offset])));
+
+               cache->current_depth--;
+
+               ACPI_MEM_TRACKING(cache->hits++);
+               ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+                                 "Object %p from %s cache\n", object,
+                                 cache->list_name));
+
+               status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
+               if (ACPI_FAILURE(status)) {
+                       return (NULL);
+               }
+
+               /* Clear (zero) the previously used Object */
+
+               ACPI_MEMSET(object, 0, cache->object_size);
+       } else {
+               /* The cache is empty, create a new object */
+
+               ACPI_MEM_TRACKING(cache->total_allocated++);
+
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+               if ((cache->total_allocated - cache->total_freed) >
+                   cache->max_occupied) {
+                       cache->max_occupied =
+                           cache->total_allocated - cache->total_freed;
+               }
+#endif
+
+               /* Avoid deadlock with ACPI_ALLOCATE_ZEROED */
+
+               status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
+               if (ACPI_FAILURE(status)) {
+                       return (NULL);
+               }
+
+               object = ACPI_ALLOCATE_ZEROED(cache->object_size);
+               if (!object) {
+                       return (NULL);
+               }
+       }
+
+       return (object);
+}
+#endif                         /* ACPI_USE_LOCAL_CACHE */
diff --git a/drivers/acpi/acpica/utclib.c b/drivers/acpi/acpica/utclib.c
new file mode 100644 (file)
index 0000000..19ea475
--- /dev/null
@@ -0,0 +1,749 @@
+/******************************************************************************
+ *
+ * Module Name: cmclib - Local implementation of C library functions
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+
+/*
+ * These implementations of standard C Library routines can optionally be
+ * used if a C library is not available. In general, they are less efficient
+ * than an inline or assembly implementation
+ */
+
+#define _COMPONENT          ACPI_UTILITIES
+ACPI_MODULE_NAME("cmclib")
+
+#ifndef ACPI_USE_SYSTEM_CLIBRARY
+#define NEGATIVE    1
+#define POSITIVE    0
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_memcmp (memcmp)
+ *
+ * PARAMETERS:  buffer1         - First Buffer
+ *              buffer2         - Second Buffer
+ *              count           - Maximum # of bytes to compare
+ *
+ * RETURN:      Index where Buffers mismatched, or 0 if Buffers matched
+ *
+ * DESCRIPTION: Compare two Buffers, with a maximum length
+ *
+ ******************************************************************************/
+int acpi_ut_memcmp(const char *buffer1, const char *buffer2, acpi_size count)
+{
+
+       return ((count == ACPI_SIZE_MAX) ? 0 : ((unsigned char)*buffer1 -
+                                               (unsigned char)*buffer2));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_memcpy (memcpy)
+ *
+ * PARAMETERS:  dest        - Target of the copy
+ *              src         - Source buffer to copy
+ *              count       - Number of bytes to copy
+ *
+ * RETURN:      Dest
+ *
+ * DESCRIPTION: Copy arbitrary bytes of memory
+ *
+ ******************************************************************************/
+
+void *acpi_ut_memcpy(void *dest, const void *src, acpi_size count)
+{
+       char *new = (char *)dest;
+       char *old = (char *)src;
+
+       while (count) {
+               *new = *old;
+               new++;
+               old++;
+               count--;
+       }
+
+       return (dest);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_memset (memset)
+ *
+ * PARAMETERS:  dest        - Buffer to set
+ *              value       - Value to set each byte of memory
+ *              count       - Number of bytes to set
+ *
+ * RETURN:      Dest
+ *
+ * DESCRIPTION: Initialize a buffer to a known value.
+ *
+ ******************************************************************************/
+
+void *acpi_ut_memset(void *dest, u8 value, acpi_size count)
+{
+       char *new = (char *)dest;
+
+       while (count) {
+               *new = (char)value;
+               new++;
+               count--;
+       }
+
+       return (dest);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_strlen (strlen)
+ *
+ * PARAMETERS:  string              - Null terminated string
+ *
+ * RETURN:      Length
+ *
+ * DESCRIPTION: Returns the length of the input string
+ *
+ ******************************************************************************/
+
+acpi_size acpi_ut_strlen(const char *string)
+{
+       u32 length = 0;
+
+       /* Count the string until a null is encountered */
+
+       while (*string) {
+               length++;
+               string++;
+       }
+
+       return (length);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_strcpy (strcpy)
+ *
+ * PARAMETERS:  dst_string      - Target of the copy
+ *              src_string      - The source string to copy
+ *
+ * RETURN:      dst_string
+ *
+ * DESCRIPTION: Copy a null terminated string
+ *
+ ******************************************************************************/
+
+char *acpi_ut_strcpy(char *dst_string, const char *src_string)
+{
+       char *string = dst_string;
+
+       /* Move bytes brute force */
+
+       while (*src_string) {
+               *string = *src_string;
+
+               string++;
+               src_string++;
+       }
+
+       /* Null terminate */
+
+       *string = 0;
+       return (dst_string);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_strncpy (strncpy)
+ *
+ * PARAMETERS:  dst_string      - Target of the copy
+ *              src_string      - The source string to copy
+ *              count           - Maximum # of bytes to copy
+ *
+ * RETURN:      dst_string
+ *
+ * DESCRIPTION: Copy a null terminated string, with a maximum length
+ *
+ ******************************************************************************/
+
+char *acpi_ut_strncpy(char *dst_string, const char *src_string, acpi_size count)
+{
+       char *string = dst_string;
+
+       /* Copy the string */
+
+       for (string = dst_string;
+            count && (count--, (*string++ = *src_string++));) {;
+       }
+
+       /* Pad with nulls if necessary */
+
+       while (count--) {
+               *string = 0;
+               string++;
+       }
+
+       /* Return original pointer */
+
+       return (dst_string);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_strcmp (strcmp)
+ *
+ * PARAMETERS:  string1         - First string
+ *              string2         - Second string
+ *
+ * RETURN:      Index where strings mismatched, or 0 if strings matched
+ *
+ * DESCRIPTION: Compare two null terminated strings
+ *
+ ******************************************************************************/
+
+int acpi_ut_strcmp(const char *string1, const char *string2)
+{
+
+       for (; (*string1 == *string2); string2++) {
+               if (!*string1++) {
+                       return (0);
+               }
+       }
+
+       return ((unsigned char)*string1 - (unsigned char)*string2);
+}
+
+#ifdef ACPI_FUTURE_IMPLEMENTATION
+/* Not used at this time */
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_strchr (strchr)
+ *
+ * PARAMETERS:  string          - Search string
+ *              ch              - character to search for
+ *
+ * RETURN:      Ptr to char or NULL if not found
+ *
+ * DESCRIPTION: Search a string for a character
+ *
+ ******************************************************************************/
+
+char *acpi_ut_strchr(const char *string, int ch)
+{
+
+       for (; (*string); string++) {
+               if ((*string) == (char)ch) {
+                       return ((char *)string);
+               }
+       }
+
+       return (NULL);
+}
+#endif
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_strncmp (strncmp)
+ *
+ * PARAMETERS:  string1         - First string
+ *              string2         - Second string
+ *              count           - Maximum # of bytes to compare
+ *
+ * RETURN:      Index where strings mismatched, or 0 if strings matched
+ *
+ * DESCRIPTION: Compare two null terminated strings, with a maximum length
+ *
+ ******************************************************************************/
+
+int acpi_ut_strncmp(const char *string1, const char *string2, acpi_size count)
+{
+
+       for (; count-- && (*string1 == *string2); string2++) {
+               if (!*string1++) {
+                       return (0);
+               }
+       }
+
+       return ((count == ACPI_SIZE_MAX) ? 0 : ((unsigned char)*string1 -
+                                               (unsigned char)*string2));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_strcat (Strcat)
+ *
+ * PARAMETERS:  dst_string      - Target of the copy
+ *              src_string      - The source string to copy
+ *
+ * RETURN:      dst_string
+ *
+ * DESCRIPTION: Append a null terminated string to a null terminated string
+ *
+ ******************************************************************************/
+
+char *acpi_ut_strcat(char *dst_string, const char *src_string)
+{
+       char *string;
+
+       /* Find end of the destination string */
+
+       for (string = dst_string; *string++;) {;
+       }
+
+       /* Concatenate the string */
+
+       for (--string; (*string++ = *src_string++);) {;
+       }
+
+       return (dst_string);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_strncat (strncat)
+ *
+ * PARAMETERS:  dst_string      - Target of the copy
+ *              src_string      - The source string to copy
+ *              count           - Maximum # of bytes to copy
+ *
+ * RETURN:      dst_string
+ *
+ * DESCRIPTION: Append a null terminated string to a null terminated string,
+ *              with a maximum count.
+ *
+ ******************************************************************************/
+
+char *acpi_ut_strncat(char *dst_string, const char *src_string, acpi_size count)
+{
+       char *string;
+
+       if (count) {
+
+               /* Find end of the destination string */
+
+               for (string = dst_string; *string++;) {;
+               }
+
+               /* Concatenate the string */
+
+               for (--string; (*string++ = *src_string++) && --count;) {;
+               }
+
+               /* Null terminate if necessary */
+
+               if (!count) {
+                       *string = 0;
+               }
+       }
+
+       return (dst_string);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_strstr (strstr)
+ *
+ * PARAMETERS:  string1         - Target string
+ *              string2         - Substring to search for
+ *
+ * RETURN:      Where substring match starts, Null if no match found
+ *
+ * DESCRIPTION: Checks if String2 occurs in String1. This is not really a
+ *              full implementation of strstr, only sufficient for command
+ *              matching
+ *
+ ******************************************************************************/
+
+char *acpi_ut_strstr(char *string1, char *string2)
+{
+       char *string;
+
+       if (acpi_ut_strlen(string2) > acpi_ut_strlen(string1)) {
+               return (NULL);
+       }
+
+       /* Walk entire string, comparing the letters */
+
+       for (string = string1; *string2;) {
+               if (*string2 != *string) {
+                       return (NULL);
+               }
+
+               string2++;
+               string++;
+       }
+
+       return (string1);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_strtoul (strtoul)
+ *
+ * PARAMETERS:  string          - Null terminated string
+ *              terminater      - Where a pointer to the terminating byte is
+ *                                returned
+ *              base            - Radix of the string
+ *
+ * RETURN:      Converted value
+ *
+ * DESCRIPTION: Convert a string into a 32-bit unsigned value.
+ *              Note: use acpi_ut_strtoul64 for 64-bit integers.
+ *
+ ******************************************************************************/
+
+u32 acpi_ut_strtoul(const char *string, char **terminator, u32 base)
+{
+       u32 converted = 0;
+       u32 index;
+       u32 sign;
+       const char *string_start;
+       u32 return_value = 0;
+       acpi_status status = AE_OK;
+
+       /*
+        * Save the value of the pointer to the buffer's first
+        * character, save the current errno value, and then
+        * skip over any white space in the buffer:
+        */
+       string_start = string;
+       while (ACPI_IS_SPACE(*string) || *string == '\t') {
+               ++string;
+       }
+
+       /*
+        * The buffer may contain an optional plus or minus sign.
+        * If it does, then skip over it but remember what is was:
+        */
+       if (*string == '-') {
+               sign = NEGATIVE;
+               ++string;
+       } else if (*string == '+') {
+               ++string;
+               sign = POSITIVE;
+       } else {
+               sign = POSITIVE;
+       }
+
+       /*
+        * If the input parameter Base is zero, then we need to
+        * determine if it is octal, decimal, or hexadecimal:
+        */
+       if (base == 0) {
+               if (*string == '0') {
+                       if (acpi_ut_to_lower(*(++string)) == 'x') {
+                               base = 16;
+                               ++string;
+                       } else {
+                               base = 8;
+                       }
+               } else {
+                       base = 10;
+               }
+       } else if (base < 2 || base > 36) {
+               /*
+                * The specified Base parameter is not in the domain of
+                * this function:
+                */
+               goto done;
+       }
+
+       /*
+        * For octal and hexadecimal bases, skip over the leading
+        * 0 or 0x, if they are present.
+        */
+       if (base == 8 && *string == '0') {
+               string++;
+       }
+
+       if (base == 16 &&
+           *string == '0' && acpi_ut_to_lower(*(++string)) == 'x') {
+               string++;
+       }
+
+       /*
+        * Main loop: convert the string to an unsigned long:
+        */
+       while (*string) {
+               if (ACPI_IS_DIGIT(*string)) {
+                       index = (u32)((u8)*string - '0');
+               } else {
+                       index = (u32)acpi_ut_to_upper(*string);
+                       if (ACPI_IS_UPPER(index)) {
+                               index = index - 'A' + 10;
+                       } else {
+                               goto done;
+                       }
+               }
+
+               if (index >= base) {
+                       goto done;
+               }
+
+               /*
+                * Check to see if value is out of range:
+                */
+
+               if (return_value > ((ACPI_UINT32_MAX - (u32)index) / (u32)base)) {
+                       status = AE_ERROR;
+                       return_value = 0;       /* reset */
+               } else {
+                       return_value *= base;
+                       return_value += index;
+                       converted = 1;
+               }
+
+               ++string;
+       }
+
+      done:
+       /*
+        * If appropriate, update the caller's pointer to the next
+        * unconverted character in the buffer.
+        */
+       if (terminator) {
+               if (converted == 0 && return_value == 0 && string != NULL) {
+                       *terminator = (char *)string_start;
+               } else {
+                       *terminator = (char *)string;
+               }
+       }
+
+       if (status == AE_ERROR) {
+               return_value = ACPI_UINT32_MAX;
+       }
+
+       /*
+        * If a minus sign was present, then "the conversion is negated":
+        */
+       if (sign == NEGATIVE) {
+               return_value = (ACPI_UINT32_MAX - return_value) + 1;
+       }
+
+       return (return_value);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_to_upper (TOUPPER)
+ *
+ * PARAMETERS:  c           - Character to convert
+ *
+ * RETURN:      Converted character as an int
+ *
+ * DESCRIPTION: Convert character to uppercase
+ *
+ ******************************************************************************/
+
+int acpi_ut_to_upper(int c)
+{
+
+       return (ACPI_IS_LOWER(c) ? ((c) - 0x20) : (c));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_to_lower (TOLOWER)
+ *
+ * PARAMETERS:  c           - Character to convert
+ *
+ * RETURN:      Converted character as an int
+ *
+ * DESCRIPTION: Convert character to lowercase
+ *
+ ******************************************************************************/
+
+int acpi_ut_to_lower(int c)
+{
+
+       return (ACPI_IS_UPPER(c) ? ((c) + 0x20) : (c));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    is* functions
+ *
+ * DESCRIPTION: is* functions use the ctype table below
+ *
+ ******************************************************************************/
+
+const u8 _acpi_ctype[257] = {
+       _ACPI_CN,               /* 0x00     0 NUL */
+       _ACPI_CN,               /* 0x01     1 SOH */
+       _ACPI_CN,               /* 0x02     2 STX */
+       _ACPI_CN,               /* 0x03     3 ETX */
+       _ACPI_CN,               /* 0x04     4 EOT */
+       _ACPI_CN,               /* 0x05     5 ENQ */
+       _ACPI_CN,               /* 0x06     6 ACK */
+       _ACPI_CN,               /* 0x07     7 BEL */
+       _ACPI_CN,               /* 0x08     8 BS  */
+       _ACPI_CN | _ACPI_SP,    /* 0x09     9 TAB */
+       _ACPI_CN | _ACPI_SP,    /* 0x0A    10 LF  */
+       _ACPI_CN | _ACPI_SP,    /* 0x0B    11 VT  */
+       _ACPI_CN | _ACPI_SP,    /* 0x0C    12 FF  */
+       _ACPI_CN | _ACPI_SP,    /* 0x0D    13 CR  */
+       _ACPI_CN,               /* 0x0E    14 SO  */
+       _ACPI_CN,               /* 0x0F    15 SI  */
+       _ACPI_CN,               /* 0x10    16 DLE */
+       _ACPI_CN,               /* 0x11    17 DC1 */
+       _ACPI_CN,               /* 0x12    18 DC2 */
+       _ACPI_CN,               /* 0x13    19 DC3 */
+       _ACPI_CN,               /* 0x14    20 DC4 */
+       _ACPI_CN,               /* 0x15    21 NAK */
+       _ACPI_CN,               /* 0x16    22 SYN */
+       _ACPI_CN,               /* 0x17    23 ETB */
+       _ACPI_CN,               /* 0x18    24 CAN */
+       _ACPI_CN,               /* 0x19    25 EM  */
+       _ACPI_CN,               /* 0x1A    26 SUB */
+       _ACPI_CN,               /* 0x1B    27 ESC */
+       _ACPI_CN,               /* 0x1C    28 FS  */
+       _ACPI_CN,               /* 0x1D    29 GS  */
+       _ACPI_CN,               /* 0x1E    30 RS  */
+       _ACPI_CN,               /* 0x1F    31 US  */
+       _ACPI_XS | _ACPI_SP,    /* 0x20    32 ' ' */
+       _ACPI_PU,               /* 0x21    33 '!' */
+       _ACPI_PU,               /* 0x22    34 '"' */
+       _ACPI_PU,               /* 0x23    35 '#' */
+       _ACPI_PU,               /* 0x24    36 '$' */
+       _ACPI_PU,               /* 0x25    37 '%' */
+       _ACPI_PU,               /* 0x26    38 '&' */
+       _ACPI_PU,               /* 0x27    39 ''' */
+       _ACPI_PU,               /* 0x28    40 '(' */
+       _ACPI_PU,               /* 0x29    41 ')' */
+       _ACPI_PU,               /* 0x2A    42 '*' */
+       _ACPI_PU,               /* 0x2B    43 '+' */
+       _ACPI_PU,               /* 0x2C    44 ',' */
+       _ACPI_PU,               /* 0x2D    45 '-' */
+       _ACPI_PU,               /* 0x2E    46 '.' */
+       _ACPI_PU,               /* 0x2F    47 '/' */
+       _ACPI_XD | _ACPI_DI,    /* 0x30    48 '0' */
+       _ACPI_XD | _ACPI_DI,    /* 0x31    49 '1' */
+       _ACPI_XD | _ACPI_DI,    /* 0x32    50 '2' */
+       _ACPI_XD | _ACPI_DI,    /* 0x33    51 '3' */
+       _ACPI_XD | _ACPI_DI,    /* 0x34    52 '4' */
+       _ACPI_XD | _ACPI_DI,    /* 0x35    53 '5' */
+       _ACPI_XD | _ACPI_DI,    /* 0x36    54 '6' */
+       _ACPI_XD | _ACPI_DI,    /* 0x37    55 '7' */
+       _ACPI_XD | _ACPI_DI,    /* 0x38    56 '8' */
+       _ACPI_XD | _ACPI_DI,    /* 0x39    57 '9' */
+       _ACPI_PU,               /* 0x3A    58 ':' */
+       _ACPI_PU,               /* 0x3B    59 ';' */
+       _ACPI_PU,               /* 0x3C    60 '<' */
+       _ACPI_PU,               /* 0x3D    61 '=' */
+       _ACPI_PU,               /* 0x3E    62 '>' */
+       _ACPI_PU,               /* 0x3F    63 '?' */
+       _ACPI_PU,               /* 0x40    64 '@' */
+       _ACPI_XD | _ACPI_UP,    /* 0x41    65 'A' */
+       _ACPI_XD | _ACPI_UP,    /* 0x42    66 'B' */
+       _ACPI_XD | _ACPI_UP,    /* 0x43    67 'C' */
+       _ACPI_XD | _ACPI_UP,    /* 0x44    68 'D' */
+       _ACPI_XD | _ACPI_UP,    /* 0x45    69 'E' */
+       _ACPI_XD | _ACPI_UP,    /* 0x46    70 'F' */
+       _ACPI_UP,               /* 0x47    71 'G' */
+       _ACPI_UP,               /* 0x48    72 'H' */
+       _ACPI_UP,               /* 0x49    73 'I' */
+       _ACPI_UP,               /* 0x4A    74 'J' */
+       _ACPI_UP,               /* 0x4B    75 'K' */
+       _ACPI_UP,               /* 0x4C    76 'L' */
+       _ACPI_UP,               /* 0x4D    77 'M' */
+       _ACPI_UP,               /* 0x4E    78 'N' */
+       _ACPI_UP,               /* 0x4F    79 'O' */
+       _ACPI_UP,               /* 0x50    80 'P' */
+       _ACPI_UP,               /* 0x51    81 'Q' */
+       _ACPI_UP,               /* 0x52    82 'R' */
+       _ACPI_UP,               /* 0x53    83 'S' */
+       _ACPI_UP,               /* 0x54    84 'T' */
+       _ACPI_UP,               /* 0x55    85 'U' */
+       _ACPI_UP,               /* 0x56    86 'V' */
+       _ACPI_UP,               /* 0x57    87 'W' */
+       _ACPI_UP,               /* 0x58    88 'X' */
+       _ACPI_UP,               /* 0x59    89 'Y' */
+       _ACPI_UP,               /* 0x5A    90 'Z' */
+       _ACPI_PU,               /* 0x5B    91 '[' */
+       _ACPI_PU,               /* 0x5C    92 '\' */
+       _ACPI_PU,               /* 0x5D    93 ']' */
+       _ACPI_PU,               /* 0x5E    94 '^' */
+       _ACPI_PU,               /* 0x5F    95 '_' */
+       _ACPI_PU,               /* 0x60    96 '`' */
+       _ACPI_XD | _ACPI_LO,    /* 0x61    97 'a' */
+       _ACPI_XD | _ACPI_LO,    /* 0x62    98 'b' */
+       _ACPI_XD | _ACPI_LO,    /* 0x63    99 'c' */
+       _ACPI_XD | _ACPI_LO,    /* 0x64   100 'd' */
+       _ACPI_XD | _ACPI_LO,    /* 0x65   101 'e' */
+       _ACPI_XD | _ACPI_LO,    /* 0x66   102 'f' */
+       _ACPI_LO,               /* 0x67   103 'g' */
+       _ACPI_LO,               /* 0x68   104 'h' */
+       _ACPI_LO,               /* 0x69   105 'i' */
+       _ACPI_LO,               /* 0x6A   106 'j' */
+       _ACPI_LO,               /* 0x6B   107 'k' */
+       _ACPI_LO,               /* 0x6C   108 'l' */
+       _ACPI_LO,               /* 0x6D   109 'm' */
+       _ACPI_LO,               /* 0x6E   110 'n' */
+       _ACPI_LO,               /* 0x6F   111 'o' */
+       _ACPI_LO,               /* 0x70   112 'p' */
+       _ACPI_LO,               /* 0x71   113 'q' */
+       _ACPI_LO,               /* 0x72   114 'r' */
+       _ACPI_LO,               /* 0x73   115 's' */
+       _ACPI_LO,               /* 0x74   116 't' */
+       _ACPI_LO,               /* 0x75   117 'u' */
+       _ACPI_LO,               /* 0x76   118 'v' */
+       _ACPI_LO,               /* 0x77   119 'w' */
+       _ACPI_LO,               /* 0x78   120 'x' */
+       _ACPI_LO,               /* 0x79   121 'y' */
+       _ACPI_LO,               /* 0x7A   122 'z' */
+       _ACPI_PU,               /* 0x7B   123 '{' */
+       _ACPI_PU,               /* 0x7C   124 '|' */
+       _ACPI_PU,               /* 0x7D   125 '}' */
+       _ACPI_PU,               /* 0x7E   126 '~' */
+       _ACPI_CN,               /* 0x7F   127 DEL */
+
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 to 0x8F    */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 to 0x9F    */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0 to 0xAF    */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0 to 0xBF    */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0 to 0xCF    */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0 to 0xDF    */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0 to 0xEF    */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0 to 0xFF    */
+       0                       /* 0x100 */
+};
+
+#endif                         /* ACPI_USE_SYSTEM_CLIBRARY */
index e810894..5d95166 100644 (file)
@@ -47,8 +47,9 @@
 
 #define _COMPONENT          ACPI_UTILITIES
 ACPI_MODULE_NAME("utdebug")
+
 #ifdef ACPI_DEBUG_OUTPUT
-static acpi_thread_id acpi_gbl_prev_thread_id;
+static acpi_thread_id acpi_gbl_prev_thread_id = (acpi_thread_id) 0xFFFFFFFF;
 static char *acpi_gbl_fn_entry_str = "----Entry";
 static char *acpi_gbl_fn_exit_str = "----Exit-";
 
@@ -109,7 +110,7 @@ void acpi_ut_track_stack_ptr(void)
  * RETURN:      Updated pointer to the function name
  *
  * DESCRIPTION: Remove the "Acpi" prefix from the function name, if present.
- *              This allows compiler macros such as __func__ to be used
+ *              This allows compiler macros such as __FUNCTION__ to be used
  *              with no change to the debug output.
  *
  ******************************************************************************/
@@ -222,7 +223,7 @@ ACPI_EXPORT_SYMBOL(acpi_debug_print)
  *
  * RETURN:      None
  *
- * DESCRIPTION: Print message with no headers.  Has same interface as
+ * DESCRIPTION: Print message with no headers. Has same interface as
  *              debug_print so that the same macros can be used.
  *
  ******************************************************************************/
@@ -258,7 +259,7 @@ ACPI_EXPORT_SYMBOL(acpi_debug_print_raw)
  *
  * RETURN:      None
  *
- * DESCRIPTION: Function entry trace.  Prints only if TRACE_FUNCTIONS bit is
+ * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is
  *              set in debug_level
  *
  ******************************************************************************/
@@ -290,7 +291,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_trace)
  *
  * RETURN:      None
  *
- * DESCRIPTION: Function entry trace.  Prints only if TRACE_FUNCTIONS bit is
+ * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is
  *              set in debug_level
  *
  ******************************************************************************/
@@ -299,6 +300,7 @@ acpi_ut_trace_ptr(u32 line_number,
                  const char *function_name,
                  const char *module_name, u32 component_id, void *pointer)
 {
+
        acpi_gbl_nesting_level++;
        acpi_ut_track_stack_ptr();
 
@@ -319,7 +321,7 @@ acpi_ut_trace_ptr(u32 line_number,
  *
  * RETURN:      None
  *
- * DESCRIPTION: Function entry trace.  Prints only if TRACE_FUNCTIONS bit is
+ * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is
  *              set in debug_level
  *
  ******************************************************************************/
@@ -350,7 +352,7 @@ acpi_ut_trace_str(u32 line_number,
  *
  * RETURN:      None
  *
- * DESCRIPTION: Function entry trace.  Prints only if TRACE_FUNCTIONS bit is
+ * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is
  *              set in debug_level
  *
  ******************************************************************************/
@@ -380,7 +382,7 @@ acpi_ut_trace_u32(u32 line_number,
  *
  * RETURN:      None
  *
- * DESCRIPTION: Function exit trace.  Prints only if TRACE_FUNCTIONS bit is
+ * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is
  *              set in debug_level
  *
  ******************************************************************************/
@@ -412,7 +414,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_exit)
  *
  * RETURN:      None
  *
- * DESCRIPTION: Function exit trace.  Prints only if TRACE_FUNCTIONS bit is
+ * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is
  *              set in debug_level. Prints exit status also.
  *
  ******************************************************************************/
@@ -453,7 +455,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_status_exit)
  *
  * RETURN:      None
  *
- * DESCRIPTION: Function exit trace.  Prints only if TRACE_FUNCTIONS bit is
+ * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is
  *              set in debug_level. Prints exit value also.
  *
  ******************************************************************************/
@@ -485,7 +487,7 @@ ACPI_EXPORT_SYMBOL(acpi_ut_value_exit)
  *
  * RETURN:      None
  *
- * DESCRIPTION: Function exit trace.  Prints only if TRACE_FUNCTIONS bit is
+ * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is
  *              set in debug_level. Prints exit value also.
  *
  ******************************************************************************/
@@ -511,7 +513,7 @@ acpi_ut_ptr_exit(u32 line_number,
  * PARAMETERS:  buffer              - Buffer to dump
  *              count               - Amount to dump, in bytes
  *              display             - BYTE, WORD, DWORD, or QWORD display
- *              component_ID        - Caller's component ID
+ *              offset              - Beginning buffer offset (display only)
  *
  * RETURN:      None
  *
@@ -519,7 +521,7 @@ acpi_ut_ptr_exit(u32 line_number,
  *
  ******************************************************************************/
 
-void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
+void acpi_ut_dump_buffer(u8 *buffer, u32 count, u32 display, u32 base_offset)
 {
        u32 i = 0;
        u32 j;
@@ -541,7 +543,7 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
 
                /* Print current offset */
 
-               acpi_os_printf("%6.4X: ", i);
+               acpi_os_printf("%6.4X: ", (base_offset + i));
 
                /* Print 16 hex chars */
 
@@ -623,7 +625,7 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ut_dump_buffer
+ * FUNCTION:    acpi_ut_debug_dump_buffer
  *
  * PARAMETERS:  buffer              - Buffer to dump
  *              count               - Amount to dump, in bytes
@@ -636,7 +638,8 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
  *
  ******************************************************************************/
 
-void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id)
+void
+acpi_ut_debug_dump_buffer(u8 *buffer, u32 count, u32 display, u32 component_id)
 {
 
        /* Only dump the buffer if tracing is enabled */
@@ -646,5 +649,5 @@ void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id)
                return;
        }
 
-       acpi_ut_dump_buffer2(buffer, count, display);
+       acpi_ut_dump_buffer(buffer, count, display, 0);
 }
index 5d84e19..774c3ae 100644 (file)
@@ -67,10 +67,10 @@ ACPI_MODULE_NAME("utids")
  ******************************************************************************/
 acpi_status
 acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
-                   struct acpica_device_id **return_id)
+                   struct acpi_pnp_device_id **return_id)
 {
        union acpi_operand_object *obj_desc;
-       struct acpica_device_id *hid;
+       struct acpi_pnp_device_id *hid;
        u32 length;
        acpi_status status;
 
@@ -94,16 +94,17 @@ acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
        /* Allocate a buffer for the HID */
 
        hid =
-           ACPI_ALLOCATE_ZEROED(sizeof(struct acpica_device_id) +
+           ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
                                 (acpi_size) length);
        if (!hid) {
                status = AE_NO_MEMORY;
                goto cleanup;
        }
 
-       /* Area for the string starts after DEVICE_ID struct */
+       /* Area for the string starts after PNP_DEVICE_ID struct */
 
-       hid->string = ACPI_ADD_PTR(char, hid, sizeof(struct acpica_device_id));
+       hid->string =
+           ACPI_ADD_PTR(char, hid, sizeof(struct acpi_pnp_device_id));
 
        /* Convert EISAID to a string or simply copy existing string */
 
@@ -126,6 +127,73 @@ cleanup:
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_ut_execute_SUB
+ *
+ * PARAMETERS:  device_node         - Node for the device
+ *              return_id           - Where the _SUB is returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Executes the _SUB control method that returns the subsystem
+ *              ID of the device. The _SUB value is always a string containing
+ *              either a valid PNP or ACPI ID.
+ *
+ *              NOTE: Internal function, no parameter validation
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ut_execute_SUB(struct acpi_namespace_node *device_node,
+                   struct acpi_pnp_device_id **return_id)
+{
+       union acpi_operand_object *obj_desc;
+       struct acpi_pnp_device_id *sub;
+       u32 length;
+       acpi_status status;
+
+       ACPI_FUNCTION_TRACE(ut_execute_SUB);
+
+       status = acpi_ut_evaluate_object(device_node, METHOD_NAME__SUB,
+                                        ACPI_BTYPE_STRING, &obj_desc);
+       if (ACPI_FAILURE(status)) {
+               return_ACPI_STATUS(status);
+       }
+
+       /* Get the size of the String to be returned, includes null terminator */
+
+       length = obj_desc->string.length + 1;
+
+       /* Allocate a buffer for the SUB */
+
+       sub =
+           ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
+                                (acpi_size) length);
+       if (!sub) {
+               status = AE_NO_MEMORY;
+               goto cleanup;
+       }
+
+       /* Area for the string starts after PNP_DEVICE_ID struct */
+
+       sub->string =
+           ACPI_ADD_PTR(char, sub, sizeof(struct acpi_pnp_device_id));
+
+       /* Simply copy existing string */
+
+       ACPI_STRCPY(sub->string, obj_desc->string.pointer);
+       sub->length = length;
+       *return_id = sub;
+
+      cleanup:
+
+       /* On exit, we must delete the return object */
+
+       acpi_ut_remove_reference(obj_desc);
+       return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_ut_execute_UID
  *
  * PARAMETERS:  device_node         - Node for the device
@@ -144,10 +212,10 @@ cleanup:
 
 acpi_status
 acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
-                   struct acpica_device_id **return_id)
+                   struct acpi_pnp_device_id **return_id)
 {
        union acpi_operand_object *obj_desc;
-       struct acpica_device_id *uid;
+       struct acpi_pnp_device_id *uid;
        u32 length;
        acpi_status status;
 
@@ -171,16 +239,17 @@ acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
        /* Allocate a buffer for the UID */
 
        uid =
-           ACPI_ALLOCATE_ZEROED(sizeof(struct acpica_device_id) +
+           ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
                                 (acpi_size) length);
        if (!uid) {
                status = AE_NO_MEMORY;
                goto cleanup;
        }
 
-       /* Area for the string starts after DEVICE_ID struct */
+       /* Area for the string starts after PNP_DEVICE_ID struct */
 
-       uid->string = ACPI_ADD_PTR(char, uid, sizeof(struct acpica_device_id));
+       uid->string =
+           ACPI_ADD_PTR(char, uid, sizeof(struct acpi_pnp_device_id));
 
        /* Convert an Integer to string, or just copy an existing string */
 
@@ -226,11 +295,11 @@ cleanup:
 
 acpi_status
 acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
-                   struct acpica_device_id_list **return_cid_list)
+                   struct acpi_pnp_device_id_list **return_cid_list)
 {
        union acpi_operand_object **cid_objects;
        union acpi_operand_object *obj_desc;
-       struct acpica_device_id_list *cid_list;
+       struct acpi_pnp_device_id_list *cid_list;
        char *next_id_string;
        u32 string_area_size;
        u32 length;
@@ -288,11 +357,12 @@ acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
        /*
         * Now that we know the length of the CIDs, allocate return buffer:
         * 1) Size of the base structure +
-        * 2) Size of the CID DEVICE_ID array +
+        * 2) Size of the CID PNP_DEVICE_ID array +
         * 3) Size of the actual CID strings
         */
-       cid_list_size = sizeof(struct acpica_device_id_list) +
-           ((count - 1) * sizeof(struct acpica_device_id)) + string_area_size;
+       cid_list_size = sizeof(struct acpi_pnp_device_id_list) +
+           ((count - 1) * sizeof(struct acpi_pnp_device_id)) +
+           string_area_size;
 
        cid_list = ACPI_ALLOCATE_ZEROED(cid_list_size);
        if (!cid_list) {
@@ -300,10 +370,10 @@ acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
                goto cleanup;
        }
 
-       /* Area for CID strings starts after the CID DEVICE_ID array */
+       /* Area for CID strings starts after the CID PNP_DEVICE_ID array */
 
        next_id_string = ACPI_CAST_PTR(char, cid_list->ids) +
-           ((acpi_size) count * sizeof(struct acpica_device_id));
+           ((acpi_size) count * sizeof(struct acpi_pnp_device_id));
 
        /* Copy/convert the CIDs to the return buffer */
 
index d88a8aa..4956367 100644 (file)
@@ -81,7 +81,7 @@ typedef union uint64_overlay {
  * RETURN:      Status (Checks for divide-by-zero)
  *
  * DESCRIPTION: Perform a short (maximum 64 bits divided by 32 bits)
- *              divide and modulo.  The result is a 64-bit quotient and a
+ *              divide and modulo. The result is a 64-bit quotient and a
  *              32-bit remainder.
  *
  ******************************************************************************/
index 33c6cf7..9286a69 100644 (file)
@@ -41,8 +41,6 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/module.h>
-
 #include <acpi/acpi.h>
 #include "accommon.h"
 #include "acnamesp.h"
@@ -201,8 +199,8 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
                                 */
                                acpi_gbl_owner_id_mask[j] |= (1 << k);
 
-                               acpi_gbl_last_owner_id_index = (u8) j;
-                               acpi_gbl_next_owner_id_offset = (u8) (k + 1);
+                               acpi_gbl_last_owner_id_index = (u8)j;
+                               acpi_gbl_next_owner_id_offset = (u8)(k + 1);
 
                                /*
                                 * Construct encoded ID from the index and bit position
@@ -252,7 +250,7 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
  *              control method or unloading a table. Either way, we would
  *              ignore any error anyway.
  *
- * DESCRIPTION: Release a table or method owner ID.  Valid IDs are 1 - 255
+ * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255
  *
  ******************************************************************************/
 
@@ -339,6 +337,73 @@ void acpi_ut_strupr(char *src_string)
        return;
 }
 
+#ifdef ACPI_ASL_COMPILER
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_strlwr (strlwr)
+ *
+ * PARAMETERS:  src_string      - The source string to convert
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Convert string to lowercase
+ *
+ * NOTE: This is not a POSIX function, so it appears here, not in utclib.c
+ *
+ ******************************************************************************/
+
+void acpi_ut_strlwr(char *src_string)
+{
+       char *string;
+
+       ACPI_FUNCTION_ENTRY();
+
+       if (!src_string) {
+               return;
+       }
+
+       /* Walk entire string, lowercasing the letters */
+
+       for (string = src_string; *string; string++) {
+               *string = (char)ACPI_TOLOWER(*string);
+       }
+
+       return;
+}
+
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_stricmp
+ *
+ * PARAMETERS:  string1             - first string to compare
+ *              string2             - second string to compare
+ *
+ * RETURN:      int that signifies string relationship. Zero means strings
+ *              are equal.
+ *
+ * DESCRIPTION: Implementation of the non-ANSI stricmp function (compare
+ *              strings with no case sensitivity)
+ *
+ ******************************************************************************/
+
+int acpi_ut_stricmp(char *string1, char *string2)
+{
+       int c1;
+       int c2;
+
+       do {
+               c1 = tolower((int)*string1);
+               c2 = tolower((int)*string2);
+
+               string1++;
+               string2++;
+       }
+       while ((c1 == c2) && (c1));
+
+       return (c1 - c2);
+}
+#endif
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ut_print_string
@@ -469,8 +534,8 @@ u32 acpi_ut_dword_byte_swap(u32 value)
  * RETURN:      None
  *
  * DESCRIPTION: Set the global integer bit width based upon the revision
- *              of the DSDT.  For Revision 1 and 0, Integers are 32 bits.
- *              For Revision 2 and above, Integers are 64 bits.  Yes, this
+ *              of the DSDT. For Revision 1 and 0, Integers are 32 bits.
+ *              For Revision 2 and above, Integers are 64 bits. Yes, this
  *              makes a difference.
  *
  ******************************************************************************/
@@ -606,7 +671,7 @@ u8 acpi_ut_valid_acpi_char(char character, u32 position)
  *
  * RETURN:      TRUE if the name is valid, FALSE otherwise
  *
- * DESCRIPTION: Check for a valid ACPI name.  Each character must be one of:
+ * DESCRIPTION: Check for a valid ACPI name. Each character must be one of:
  *              1) Upper case alpha
  *              2) numeric
  *              3) underscore
@@ -638,29 +703,59 @@ u8 acpi_ut_valid_acpi_name(u32 name)
  * RETURN:      Repaired version of the name
  *
  * DESCRIPTION: Repair an ACPI name: Change invalid characters to '*' and
- *              return the new name.
+ *              return the new name. NOTE: the Name parameter must reside in
+ *              read/write memory, cannot be a const.
+ *
+ * An ACPI Name must consist of valid ACPI characters. We will repair the name
+ * if necessary because we don't want to abort because of this, but we want
+ * all namespace names to be printable. A warning message is appropriate.
+ *
+ * This issue came up because there are in fact machines that exhibit
+ * this problem, and we want to be able to enable ACPI support for them,
+ * even though there are a few bad names.
  *
  ******************************************************************************/
 
-acpi_name acpi_ut_repair_name(char *name)
+void acpi_ut_repair_name(char *name)
 {
-       u32 i;
-       char new_name[ACPI_NAME_SIZE];
+       u32 i;
+       u8 found_bad_char = FALSE;
+       u32 original_name;
+
+       ACPI_FUNCTION_NAME(ut_repair_name);
+
+       ACPI_MOVE_NAME(&original_name, name);
+
+       /* Check each character in the name */
 
        for (i = 0; i < ACPI_NAME_SIZE; i++) {
-               new_name[i] = name[i];
+               if (acpi_ut_valid_acpi_char(name[i], i)) {
+                       continue;
+               }
 
                /*
                 * Replace a bad character with something printable, yet technically
                 * still invalid. This prevents any collisions with existing "good"
                 * names in the namespace.
                 */
-               if (!acpi_ut_valid_acpi_char(name[i], i)) {
-                       new_name[i] = '*';
-               }
+               name[i] = '*';
+               found_bad_char = TRUE;
        }
 
-       return (*(u32 *) new_name);
+       if (found_bad_char) {
+
+               /* Report warning only if in strict mode or debug mode */
+
+               if (!acpi_gbl_enable_interpreter_slack) {
+                       ACPI_WARNING((AE_INFO,
+                                     "Found bad character(s) in name, repaired: [%4.4s]\n",
+                                     name));
+               } else {
+                       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                                         "Found bad character(s) in name, repaired: [%4.4s]\n",
+                                         name));
+               }
+       }
 }
 
 /*******************************************************************************
@@ -681,7 +776,7 @@ acpi_name acpi_ut_repair_name(char *name)
  *
  ******************************************************************************/
 
-acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 * ret_integer)
+acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer)
 {
        u32 this_digit = 0;
        u64 return_value = 0;
@@ -754,14 +849,14 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 * ret_integer)
 
                        /* Convert ASCII 0-9 to Decimal value */
 
-                       this_digit = ((u8) * string) - '0';
+                       this_digit = ((u8)*string) - '0';
                } else if (base == 10) {
 
                        /* Digit is out of range; possible in to_integer case only */
 
                        term = 1;
                } else {
-                       this_digit = (u8) ACPI_TOUPPER(*string);
+                       this_digit = (u8)ACPI_TOUPPER(*string);
                        if (ACPI_IS_XDIGIT((char)this_digit)) {
 
                                /* Convert ASCII Hex char to value */
@@ -788,8 +883,9 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 * ret_integer)
 
                valid_digits++;
 
-               if (sign_of0x && ((valid_digits > 16)
-                                 || ((valid_digits > 8) && mode32))) {
+               if (sign_of0x
+                   && ((valid_digits > 16)
+                       || ((valid_digits > 8) && mode32))) {
                        /*
                         * This is to_integer operation case.
                         * No any restrictions for string-to-integer conversion,
@@ -800,7 +896,7 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 * ret_integer)
 
                /* Divide the digit into the correct position */
 
-               (void)acpi_ut_short_divide((dividend - (u64) this_digit),
+               (void)acpi_ut_short_divide((dividend - (u64)this_digit),
                                           base, &quotient, NULL);
 
                if (return_value > quotient) {
@@ -890,7 +986,7 @@ acpi_ut_create_update_state_and_push(union acpi_operand_object *object,
  ******************************************************************************/
 
 acpi_status
-acpi_ut_walk_package_tree(union acpi_operand_object * source_object,
+acpi_ut_walk_package_tree(union acpi_operand_object *source_object,
                          void *target_object,
                          acpi_pkg_callback walk_callback, void *context)
 {
@@ -917,10 +1013,10 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object,
 
                /*
                 * Check for:
-                * 1) An uninitialized package element.  It is completely
+                * 1) An uninitialized package element. It is completely
                 *    legal to declare a package and leave it uninitialized
                 * 2) Not an internal object - can be a namespace node instead
-                * 3) Any type other than a package.  Packages are handled in else
+                * 3) Any type other than a package. Packages are handled in else
                 *    case below.
                 */
                if ((!this_source_obj) ||
@@ -939,7 +1035,7 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object,
                               state->pkg.source_object->package.count) {
                                /*
                                 * We've handled all of the objects at this level,  This means
-                                * that we have just completed a package.  That package may
+                                * that we have just completed a package. That package may
                                 * have contained one or more packages itself.
                                 *
                                 * Delete this state and pop the previous state (package).
index 296baa6..5ccf57c 100644 (file)
@@ -193,6 +193,8 @@ static void acpi_ut_delete_mutex(acpi_mutex_handle mutex_id)
 
        acpi_gbl_mutex_info[mutex_id].mutex = NULL;
        acpi_gbl_mutex_info[mutex_id].thread_id = ACPI_MUTEX_NOT_ACQUIRED;
+
+       return_VOID;
 }
 
 /*******************************************************************************
@@ -226,9 +228,9 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
                /*
                 * Mutex debug code, for internal debugging only.
                 *
-                * Deadlock prevention.  Check if this thread owns any mutexes of value
-                * greater than or equal to this one.  If so, the thread has violated
-                * the mutex ordering rule.  This indicates a coding error somewhere in
+                * Deadlock prevention. Check if this thread owns any mutexes of value
+                * greater than or equal to this one. If so, the thread has violated
+                * the mutex ordering rule. This indicates a coding error somewhere in
                 * the ACPI subsystem code.
                 */
                for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) {
@@ -319,9 +321,9 @@ acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
                /*
                 * Mutex debug code, for internal debugging only.
                 *
-                * Deadlock prevention.  Check if this thread owns any mutexes of value
-                * greater than this one.  If so, the thread has violated the mutex
-                * ordering rule.  This indicates a coding error somewhere in
+                * Deadlock prevention. Check if this thread owns any mutexes of value
+                * greater than this one. If so, the thread has violated the mutex
+                * ordering rule. This indicates a coding error somewhere in
                 * the ACPI subsystem code.
                 */
                for (i = mutex_id; i < ACPI_NUM_MUTEX; i++) {
index 655f079..5c52ca7 100644 (file)
@@ -77,7 +77,7 @@ acpi_ut_get_element_length(u8 object_type,
  *
  * NOTE:        We always allocate the worst-case object descriptor because
  *              these objects are cached, and we want them to be
- *              one-size-satisifies-any-request.  This in itself may not be
+ *              one-size-satisifies-any-request. This in itself may not be
  *              the most memory efficient, but the efficiency of the object
  *              cache should more than make up for this!
  *
@@ -370,9 +370,9 @@ u8 acpi_ut_valid_internal_object(void *object)
  *              line_number         - Caller's line number (for error output)
  *              component_id        - Caller's component ID (for error output)
  *
- * RETURN:      Pointer to newly allocated object descriptor.  Null on error
+ * RETURN:      Pointer to newly allocated object descriptor. Null on error
  *
- * DESCRIPTION: Allocate a new object descriptor.  Gracefully handle
+ * DESCRIPTION: Allocate a new object descriptor. Gracefully handle
  *              error conditions.
  *
  ******************************************************************************/
@@ -554,7 +554,7 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
 
        /*
         * Account for the space required by the object rounded up to the next
-        * multiple of the machine word size.  This keeps each object aligned
+        * multiple of the machine word size. This keeps each object aligned
         * on a machine word boundary. (preventing alignment faults on some
         * machines.)
         */
index a1c9882..cee0473 100644 (file)
@@ -147,7 +147,7 @@ union acpi_generic_state *acpi_ut_pop_generic_state(union acpi_generic_state
  *
  * RETURN:      The new state object. NULL on failure.
  *
- * DESCRIPTION: Create a generic state object.  Attempt to obtain one from
+ * DESCRIPTION: Create a generic state object. Attempt to obtain one from
  *              the global state cache;  If none available, create a new one.
  *
  ******************************************************************************/
diff --git a/drivers/acpi/acpica/uttrack.c b/drivers/acpi/acpica/uttrack.c
new file mode 100644 (file)
index 0000000..a424a9e
--- /dev/null
@@ -0,0 +1,692 @@
+/******************************************************************************
+ *
+ * Module Name: uttrack - Memory allocation tracking routines (debug only)
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2012, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+/*
+ * These procedures are used for tracking memory leaks in the subsystem, and
+ * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set.
+ *
+ * Each memory allocation is tracked via a doubly linked list. Each
+ * element contains the caller's component, module name, function name, and
+ * line number. acpi_ut_allocate and acpi_ut_allocate_zeroed call
+ * acpi_ut_track_allocation to add an element to the list; deletion
+ * occurs in the body of acpi_ut_free.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+
+#define _COMPONENT          ACPI_UTILITIES
+ACPI_MODULE_NAME("uttrack")
+
+/* Local prototypes */
+static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct
+                                                           acpi_debug_mem_block
+                                                           *allocation);
+
+static acpi_status
+acpi_ut_track_allocation(struct acpi_debug_mem_block *address,
+                        acpi_size size,
+                        u8 alloc_type,
+                        u32 component, const char *module, u32 line);
+
+static acpi_status
+acpi_ut_remove_allocation(struct acpi_debug_mem_block *address,
+                         u32 component, const char *module, u32 line);
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_create_list
+ *
+ * PARAMETERS:  cache_name      - Ascii name for the cache
+ *              object_size     - Size of each cached object
+ *              return_cache    - Where the new cache object is returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Create a local memory list for tracking purposed
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ut_create_list(char *list_name,
+                   u16 object_size, struct acpi_memory_list **return_cache)
+{
+       struct acpi_memory_list *cache;
+
+       cache = acpi_os_allocate(sizeof(struct acpi_memory_list));
+       if (!cache) {
+               return (AE_NO_MEMORY);
+       }
+
+       ACPI_MEMSET(cache, 0, sizeof(struct acpi_memory_list));
+
+       cache->list_name = list_name;
+       cache->object_size = object_size;
+
+       *return_cache = cache;
+       return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_allocate_and_track
+ *
+ * PARAMETERS:  size                - Size of the allocation
+ *              component           - Component type of caller
+ *              module              - Source file name of caller
+ *              line                - Line number of caller
+ *
+ * RETURN:      Address of the allocated memory on success, NULL on failure.
+ *
+ * DESCRIPTION: The subsystem's equivalent of malloc.
+ *
+ ******************************************************************************/
+
+void *acpi_ut_allocate_and_track(acpi_size size,
+                                u32 component, const char *module, u32 line)
+{
+       struct acpi_debug_mem_block *allocation;
+       acpi_status status;
+
+       allocation =
+           acpi_ut_allocate(size + sizeof(struct acpi_debug_mem_header),
+                            component, module, line);
+       if (!allocation) {
+               return (NULL);
+       }
+
+       status = acpi_ut_track_allocation(allocation, size,
+                                         ACPI_MEM_MALLOC, component, module,
+                                         line);
+       if (ACPI_FAILURE(status)) {
+               acpi_os_free(allocation);
+               return (NULL);
+       }
+
+       acpi_gbl_global_list->total_allocated++;
+       acpi_gbl_global_list->total_size += (u32)size;
+       acpi_gbl_global_list->current_total_size += (u32)size;
+       if (acpi_gbl_global_list->current_total_size >
+           acpi_gbl_global_list->max_occupied) {
+               acpi_gbl_global_list->max_occupied =
+                   acpi_gbl_global_list->current_total_size;
+       }
+
+       return ((void *)&allocation->user_space);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_allocate_zeroed_and_track
+ *
+ * PARAMETERS:  size                - Size of the allocation
+ *              component           - Component type of caller
+ *              module              - Source file name of caller
+ *              line                - Line number of caller
+ *
+ * RETURN:      Address of the allocated memory on success, NULL on failure.
+ *
+ * DESCRIPTION: Subsystem equivalent of calloc.
+ *
+ ******************************************************************************/
+
+void *acpi_ut_allocate_zeroed_and_track(acpi_size size,
+                                       u32 component,
+                                       const char *module, u32 line)
+{
+       struct acpi_debug_mem_block *allocation;
+       acpi_status status;
+
+       allocation =
+           acpi_ut_allocate_zeroed(size + sizeof(struct acpi_debug_mem_header),
+                                   component, module, line);
+       if (!allocation) {
+
+               /* Report allocation error */
+
+               ACPI_ERROR((module, line,
+                           "Could not allocate size %u", (u32)size));
+               return (NULL);
+       }
+
+       status = acpi_ut_track_allocation(allocation, size,
+                                         ACPI_MEM_CALLOC, component, module,
+                                         line);
+       if (ACPI_FAILURE(status)) {
+               acpi_os_free(allocation);
+               return (NULL);
+       }
+
+       acpi_gbl_global_list->total_allocated++;
+       acpi_gbl_global_list->total_size += (u32)size;
+       acpi_gbl_global_list->current_total_size += (u32)size;
+       if (acpi_gbl_global_list->current_total_size >
+           acpi_gbl_global_list->max_occupied) {
+               acpi_gbl_global_list->max_occupied =
+                   acpi_gbl_global_list->current_total_size;
+       }
+
+       return ((void *)&allocation->user_space);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_free_and_track
+ *
+ * PARAMETERS:  allocation          - Address of the memory to deallocate
+ *              component           - Component type of caller
+ *              module              - Source file name of caller
+ *              line                - Line number of caller
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Frees the memory at Allocation
+ *
+ ******************************************************************************/
+
+void
+acpi_ut_free_and_track(void *allocation,
+                      u32 component, const char *module, u32 line)
+{
+       struct acpi_debug_mem_block *debug_block;
+       acpi_status status;
+
+       ACPI_FUNCTION_TRACE_PTR(ut_free, allocation);
+
+       if (NULL == allocation) {
+               ACPI_ERROR((module, line, "Attempt to delete a NULL address"));
+
+               return_VOID;
+       }
+
+       debug_block = ACPI_CAST_PTR(struct acpi_debug_mem_block,
+                                   (((char *)allocation) -
+                                    sizeof(struct acpi_debug_mem_header)));
+
+       acpi_gbl_global_list->total_freed++;
+       acpi_gbl_global_list->current_total_size -= debug_block->size;
+
+       status = acpi_ut_remove_allocation(debug_block,
+                                          component, module, line);
+       if (ACPI_FAILURE(status)) {
+               ACPI_EXCEPTION((AE_INFO, status, "Could not free memory"));
+       }
+
+       acpi_os_free(debug_block);
+       ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p freed\n", allocation));
+       return_VOID;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_find_allocation
+ *
+ * PARAMETERS:  allocation              - Address of allocated memory
+ *
+ * RETURN:      Three cases:
+ *              1) List is empty, NULL is returned.
+ *              2) Element was found. Returns Allocation parameter.
+ *              3) Element was not found. Returns position where it should be
+ *                  inserted into the list.
+ *
+ * DESCRIPTION: Searches for an element in the global allocation tracking list.
+ *              If the element is not found, returns the location within the
+ *              list where the element should be inserted.
+ *
+ *              Note: The list is ordered by larger-to-smaller addresses.
+ *
+ *              This global list is used to detect memory leaks in ACPICA as
+ *              well as other issues such as an attempt to release the same
+ *              internal object more than once. Although expensive as far
+ *              as cpu time, this list is much more helpful for finding these
+ *              types of issues than using memory leak detectors outside of
+ *              the ACPICA code.
+ *
+ ******************************************************************************/
+
+static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct
+                                                           acpi_debug_mem_block
+                                                           *allocation)
+{
+       struct acpi_debug_mem_block *element;
+
+       element = acpi_gbl_global_list->list_head;
+       if (!element) {
+               return (NULL);
+       }
+
+       /*
+        * Search for the address.
+        *
+        * Note: List is ordered by larger-to-smaller addresses, on the
+        * assumption that a new allocation usually has a larger address
+        * than previous allocations.
+        */
+       while (element > allocation) {
+
+               /* Check for end-of-list */
+
+               if (!element->next) {
+                       return (element);
+               }
+
+               element = element->next;
+       }
+
+       if (element == allocation) {
+               return (element);
+       }
+
+       return (element->previous);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_track_allocation
+ *
+ * PARAMETERS:  allocation          - Address of allocated memory
+ *              size                - Size of the allocation
+ *              alloc_type          - MEM_MALLOC or MEM_CALLOC
+ *              component           - Component type of caller
+ *              module              - Source file name of caller
+ *              line                - Line number of caller
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Inserts an element into the global allocation tracking list.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation,
+                        acpi_size size,
+                        u8 alloc_type,
+                        u32 component, const char *module, u32 line)
+{
+       struct acpi_memory_list *mem_list;
+       struct acpi_debug_mem_block *element;
+       acpi_status status = AE_OK;
+
+       ACPI_FUNCTION_TRACE_PTR(ut_track_allocation, allocation);
+
+       if (acpi_gbl_disable_mem_tracking) {
+               return_ACPI_STATUS(AE_OK);
+       }
+
+       mem_list = acpi_gbl_global_list;
+       status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY);
+       if (ACPI_FAILURE(status)) {
+               return_ACPI_STATUS(status);
+       }
+
+       /*
+        * Search the global list for this address to make sure it is not
+        * already present. This will catch several kinds of problems.
+        */
+       element = acpi_ut_find_allocation(allocation);
+       if (element == allocation) {
+               ACPI_ERROR((AE_INFO,
+                           "UtTrackAllocation: Allocation (%p) already present in global list!",
+                           allocation));
+               goto unlock_and_exit;
+       }
+
+       /* Fill in the instance data */
+
+       allocation->size = (u32)size;
+       allocation->alloc_type = alloc_type;
+       allocation->component = component;
+       allocation->line = line;
+
+       ACPI_STRNCPY(allocation->module, module, ACPI_MAX_MODULE_NAME);
+       allocation->module[ACPI_MAX_MODULE_NAME - 1] = 0;
+
+       if (!element) {
+
+               /* Insert at list head */
+
+               if (mem_list->list_head) {
+                       ((struct acpi_debug_mem_block *)(mem_list->list_head))->
+                           previous = allocation;
+               }
+
+               allocation->next = mem_list->list_head;
+               allocation->previous = NULL;
+
+               mem_list->list_head = allocation;
+       } else {
+               /* Insert after element */
+
+               allocation->next = element->next;
+               allocation->previous = element;
+
+               if (element->next) {
+                       (element->next)->previous = allocation;
+               }
+
+               element->next = allocation;
+       }
+
+      unlock_and_exit:
+       status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
+       return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_remove_allocation
+ *
+ * PARAMETERS:  allocation          - Address of allocated memory
+ *              component           - Component type of caller
+ *              module              - Source file name of caller
+ *              line                - Line number of caller
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Deletes an element from the global allocation tracking list.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation,
+                         u32 component, const char *module, u32 line)
+{
+       struct acpi_memory_list *mem_list;
+       acpi_status status;
+
+       ACPI_FUNCTION_TRACE(ut_remove_allocation);
+
+       if (acpi_gbl_disable_mem_tracking) {
+               return_ACPI_STATUS(AE_OK);
+       }
+
+       mem_list = acpi_gbl_global_list;
+       if (NULL == mem_list->list_head) {
+
+               /* No allocations! */
+
+               ACPI_ERROR((module, line,
+                           "Empty allocation list, nothing to free!"));
+
+               return_ACPI_STATUS(AE_OK);
+       }
+
+       status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY);
+       if (ACPI_FAILURE(status)) {
+               return_ACPI_STATUS(status);
+       }
+
+       /* Unlink */
+
+       if (allocation->previous) {
+               (allocation->previous)->next = allocation->next;
+       } else {
+               mem_list->list_head = allocation->next;
+       }
+
+       if (allocation->next) {
+               (allocation->next)->previous = allocation->previous;
+       }
+
+       /* Mark the segment as deleted */
+
+       ACPI_MEMSET(&allocation->user_space, 0xEA, allocation->size);
+
+       ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Freeing size 0%X\n",
+                         allocation->size));
+
+       status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
+       return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_dump_allocation_info
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Print some info about the outstanding allocations.
+ *
+ ******************************************************************************/
+
+void acpi_ut_dump_allocation_info(void)
+{
+/*
+       struct acpi_memory_list         *mem_list;
+*/
+
+       ACPI_FUNCTION_TRACE(ut_dump_allocation_info);
+
+/*
+       ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
+                         ("%30s: %4d (%3d Kb)\n", "Current allocations",
+                         mem_list->current_count,
+                         ROUND_UP_TO_1K (mem_list->current_size)));
+
+       ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
+                         ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations",
+                         mem_list->max_concurrent_count,
+                         ROUND_UP_TO_1K (mem_list->max_concurrent_size)));
+
+       ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
+                         ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects",
+                         running_object_count,
+                         ROUND_UP_TO_1K (running_object_size)));
+
+       ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
+                         ("%30s: %4d (%3d Kb)\n", "Total (all) allocations",
+                         running_alloc_count,
+                         ROUND_UP_TO_1K (running_alloc_size)));
+
+       ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
+                         ("%30s: %4d (%3d Kb)\n", "Current Nodes",
+                         acpi_gbl_current_node_count,
+                         ROUND_UP_TO_1K (acpi_gbl_current_node_size)));
+
+       ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
+                         ("%30s: %4d (%3d Kb)\n", "Max Nodes",
+                         acpi_gbl_max_concurrent_node_count,
+                         ROUND_UP_TO_1K ((acpi_gbl_max_concurrent_node_count *
+                                        sizeof (struct acpi_namespace_node)))));
+*/
+       return_VOID;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_dump_allocations
+ *
+ * PARAMETERS:  component           - Component(s) to dump info for.
+ *              module              - Module to dump info for. NULL means all.
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Print a list of all outstanding allocations.
+ *
+ ******************************************************************************/
+
+void acpi_ut_dump_allocations(u32 component, const char *module)
+{
+       struct acpi_debug_mem_block *element;
+       union acpi_descriptor *descriptor;
+       u32 num_outstanding = 0;
+       u8 descriptor_type;
+
+       ACPI_FUNCTION_TRACE(ut_dump_allocations);
+
+       if (acpi_gbl_disable_mem_tracking) {
+               return_VOID;
+       }
+
+       /*
+        * Walk the allocation list.
+        */
+       if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_MEMORY))) {
+               return_VOID;
+       }
+
+       element = acpi_gbl_global_list->list_head;
+       while (element) {
+               if ((element->component & component) &&
+                   ((module == NULL)
+                    || (0 == ACPI_STRCMP(module, element->module)))) {
+                       descriptor =
+                           ACPI_CAST_PTR(union acpi_descriptor,
+                                         &element->user_space);
+
+                       if (element->size <
+                           sizeof(struct acpi_common_descriptor)) {
+                               acpi_os_printf("%p Length 0x%04X %9.9s-%u "
+                                              "[Not a Descriptor - too small]\n",
+                                              descriptor, element->size,
+                                              element->module, element->line);
+                       } else {
+                               /* Ignore allocated objects that are in a cache */
+
+                               if (ACPI_GET_DESCRIPTOR_TYPE(descriptor) !=
+                                   ACPI_DESC_TYPE_CACHED) {
+                                       acpi_os_printf
+                                           ("%p Length 0x%04X %9.9s-%u [%s] ",
+                                            descriptor, element->size,
+                                            element->module, element->line,
+                                            acpi_ut_get_descriptor_name
+                                            (descriptor));
+
+                                       /* Validate the descriptor type using Type field and length */
+
+                                       descriptor_type = 0;    /* Not a valid descriptor type */
+
+                                       switch (ACPI_GET_DESCRIPTOR_TYPE
+                                               (descriptor)) {
+                                       case ACPI_DESC_TYPE_OPERAND:
+                                               if (element->size ==
+                                                   sizeof(union
+                                                          acpi_operand_object))
+                                               {
+                                                       descriptor_type =
+                                                           ACPI_DESC_TYPE_OPERAND;
+                                               }
+                                               break;
+
+                                       case ACPI_DESC_TYPE_PARSER:
+                                               if (element->size ==
+                                                   sizeof(union
+                                                          acpi_parse_object)) {
+                                                       descriptor_type =
+                                                           ACPI_DESC_TYPE_PARSER;
+                                               }
+                                               break;
+
+                                       case ACPI_DESC_TYPE_NAMED:
+                                               if (element->size ==
+                                                   sizeof(struct
+                                                          acpi_namespace_node))
+                                               {
+                                                       descriptor_type =
+                                                           ACPI_DESC_TYPE_NAMED;
+                                               }
+                                               break;
+
+                                       default:
+                                               break;
+                                       }
+
+                                       /* Display additional info for the major descriptor types */
+
+                                       switch (descriptor_type) {
+                                       case ACPI_DESC_TYPE_OPERAND:
+                                               acpi_os_printf
+                                                   ("%12.12s RefCount 0x%04X\n",
+                                                    acpi_ut_get_type_name
+                                                    (descriptor->object.common.
+                                                     type),
+                                                    descriptor->object.common.
+                                                    reference_count);
+                                               break;
+
+                                       case ACPI_DESC_TYPE_PARSER:
+                                               acpi_os_printf
+                                                   ("AmlOpcode 0x%04hX\n",
+                                                    descriptor->op.asl.
+                                                    aml_opcode);
+                                               break;
+
+                                       case ACPI_DESC_TYPE_NAMED:
+                                               acpi_os_printf("%4.4s\n",
+                                                              acpi_ut_get_node_name
+                                                              (&descriptor->
+                                                               node));
+                                               break;
+
+                                       default:
+                                               acpi_os_printf("\n");
+                                               break;
+                                       }
+                               }
+                       }
+
+                       num_outstanding++;
+               }
+
+               element = element->next;
+       }
+
+       (void)acpi_ut_release_mutex(ACPI_MTX_MEMORY);
+
+       /* Print summary */
+
+       if (!num_outstanding) {
+               ACPI_INFO((AE_INFO, "No outstanding allocations"));
+       } else {
+               ACPI_ERROR((AE_INFO, "%u(0x%X) Outstanding allocations",
+                           num_outstanding, num_outstanding));
+       }
+
+       return_VOID;
+}
+
+#endif                         /* ACPI_DBG_TRACK_ALLOCATIONS */
index b09632b..390db0c 100644 (file)
@@ -147,7 +147,7 @@ ACPI_EXPORT_SYMBOL(acpi_subsystem_status)
  * RETURN:      status          - the status of the call
  *
  * DESCRIPTION: This function is called to get information about the current
- *              state of the ACPI subsystem.  It will return system information
+ *              state of the ACPI subsystem. It will return system information
  *              in the out_buffer.
  *
  *              If the function fails an appropriate status will be returned
@@ -238,7 +238,7 @@ acpi_install_initialization_handler(acpi_init_handler handler, u32 function)
        }
 
        acpi_gbl_init_handler = handler;
-       return AE_OK;
+       return (AE_OK);
 }
 
 ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler)
@@ -263,6 +263,7 @@ acpi_status acpi_purge_cached_objects(void)
        (void)acpi_os_purge_cache(acpi_gbl_operand_cache);
        (void)acpi_os_purge_cache(acpi_gbl_ps_node_cache);
        (void)acpi_os_purge_cache(acpi_gbl_ps_node_ext_cache);
+
        return_ACPI_STATUS(AE_OK);
 }
 
index 6d63cc3..d4d3826 100644 (file)
@@ -408,7 +408,7 @@ acpi_ut_namespace_error(const char *module_name,
 
                ACPI_MOVE_32_TO_32(&bad_name,
                                   ACPI_CAST_PTR(u32, internal_name));
-               acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name);
+               acpi_os_printf("[0x%.8X] (NON-ASCII)", bad_name);
        } else {
                /* Convert path to external format */
 
index 1599566..da93c00 100644 (file)
@@ -994,7 +994,7 @@ err:
        return rc;
 }
 
-static int __devexit ghes_remove(struct platform_device *ghes_dev)
+static int ghes_remove(struct platform_device *ghes_dev)
 {
        struct ghes *ghes;
        struct acpi_hest_generic *generic;
index 45e3e17..7efaeaa 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/dmi.h>
 #include <linux/slab.h>
 #include <linux/suspend.h>
+#include <asm/unaligned.h>
 
 #ifdef CONFIG_ACPI_PROCFS_POWER
 #include <linux/proc_fs.h>
@@ -95,6 +96,18 @@ enum {
        ACPI_BATTERY_ALARM_PRESENT,
        ACPI_BATTERY_XINFO_PRESENT,
        ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
+       /* On Lenovo Thinkpad models from 2010 and 2011, the power unit
+          switches between mWh and mAh depending on whether the system
+          is running on battery or not.  When mAh is the unit, most
+          reported values are incorrect and need to be adjusted by
+          10000/design_voltage.  Verified on x201, t410, t410s, and x220.
+          Pre-2010 and 2012 models appear to always report in mWh and
+          are thus unaffected (tested with t42, t61, t500, x200, x300,
+          and x230).  Also, in mid-2012 Lenovo issued a BIOS update for
+          the 2011 models that fixes the issue (tested on x220 with a
+          post-1.29 BIOS), but as of Nov. 2012, no such update is
+          available for the 2010 models.  */
+       ACPI_BATTERY_QUIRK_THINKPAD_MAH,
 };
 
 struct acpi_battery {
@@ -438,6 +451,21 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
        kfree(buffer.pointer);
        if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
                battery->full_charge_capacity = battery->design_capacity;
+       if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
+           battery->power_unit && battery->design_voltage) {
+               battery->design_capacity = battery->design_capacity *
+                   10000 / battery->design_voltage;
+               battery->full_charge_capacity = battery->full_charge_capacity *
+                   10000 / battery->design_voltage;
+               battery->design_capacity_warning =
+                   battery->design_capacity_warning *
+                   10000 / battery->design_voltage;
+               /* Curiously, design_capacity_low, unlike the rest of them,
+                  is correct.  */
+               /* capacity_granularity_* equal 1 on the systems tested, so
+                  it's impossible to tell if they would need an adjustment
+                  or not if their values were higher.  */
+       }
        return result;
 }
 
@@ -486,6 +514,11 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
            && battery->capacity_now >= 0 && battery->capacity_now <= 100)
                battery->capacity_now = (battery->capacity_now *
                                battery->full_charge_capacity) / 100;
+       if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) &&
+           battery->power_unit && battery->design_voltage) {
+               battery->capacity_now = battery->capacity_now *
+                   10000 / battery->design_voltage;
+       }
        return result;
 }
 
@@ -595,6 +628,24 @@ static void sysfs_remove_battery(struct acpi_battery *battery)
        mutex_unlock(&battery->sysfs_lock);
 }
 
+static void find_battery(const struct dmi_header *dm, void *private)
+{
+       struct acpi_battery *battery = (struct acpi_battery *)private;
+       /* Note: the hardcoded offsets below have been extracted from
+          the source code of dmidecode.  */
+       if (dm->type == DMI_ENTRY_PORTABLE_BATTERY && dm->length >= 8) {
+               const u8 *dmi_data = (const u8 *)(dm + 1);
+               int dmi_capacity = get_unaligned((const u16 *)(dmi_data + 6));
+               if (dm->length >= 18)
+                       dmi_capacity *= dmi_data[17];
+               if (battery->design_capacity * battery->design_voltage / 1000
+                   != dmi_capacity &&
+                   battery->design_capacity * 10 == dmi_capacity)
+                       set_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
+                               &battery->flags);
+       }
+}
+
 /*
  * According to the ACPI spec, some kinds of primary batteries can
  * report percentage battery remaining capacity directly to OS.
@@ -620,6 +671,32 @@ static void acpi_battery_quirks(struct acpi_battery *battery)
                battery->capacity_now = (battery->capacity_now *
                                battery->full_charge_capacity) / 100;
        }
+
+       if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags))
+               return ;
+
+       if (battery->power_unit && dmi_name_in_vendors("LENOVO")) {
+               const char *s;
+               s = dmi_get_system_info(DMI_PRODUCT_VERSION);
+               if (s && !strnicmp(s, "ThinkPad", 8)) {
+                       dmi_walk(find_battery, battery);
+                       if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH,
+                                    &battery->flags) &&
+                           battery->design_voltage) {
+                               battery->design_capacity =
+                                   battery->design_capacity *
+                                   10000 / battery->design_voltage;
+                               battery->full_charge_capacity =
+                                   battery->full_charge_capacity *
+                                   10000 / battery->design_voltage;
+                               battery->design_capacity_warning =
+                                   battery->design_capacity_warning *
+                                   10000 / battery->design_voltage;
+                               battery->capacity_now = battery->capacity_now *
+                                   10000 / battery->design_voltage;
+                       }
+               }
+       }
 }
 
 static int acpi_battery_update(struct acpi_battery *battery)
index d59175e..1f0d457 100644 (file)
@@ -257,7 +257,15 @@ static int __acpi_bus_get_power(struct acpi_device *device, int *state)
 }
 
 
-static int __acpi_bus_set_power(struct acpi_device *device, int state)
+/**
+ * acpi_device_set_power - Set power state of an ACPI device.
+ * @device: Device to set the power state of.
+ * @state: New power state to set.
+ *
+ * Callers must ensure that the device is power manageable before using this
+ * function.
+ */
+int acpi_device_set_power(struct acpi_device *device, int state)
 {
        int result = 0;
        acpi_status status = AE_OK;
@@ -298,6 +306,12 @@ static int __acpi_bus_set_power(struct acpi_device *device, int state)
         * a lower-powered state.
         */
        if (state < device->power.state) {
+               if (device->power.state >= ACPI_STATE_D3_HOT &&
+                   state != ACPI_STATE_D0) {
+                       printk(KERN_WARNING PREFIX
+                             "Cannot transition to non-D0 state from D3\n");
+                       return -ENODEV;
+               }
                if (device->power.flags.power_resources) {
                        result = acpi_power_transition(device, state);
                        if (result)
@@ -341,6 +355,7 @@ static int __acpi_bus_set_power(struct acpi_device *device, int state)
 
        return result;
 }
+EXPORT_SYMBOL(acpi_device_set_power);
 
 
 int acpi_bus_set_power(acpi_handle handle, int state)
@@ -359,7 +374,7 @@ int acpi_bus_set_power(acpi_handle handle, int state)
                return -ENODEV;
        }
 
-       return __acpi_bus_set_power(device, state);
+       return acpi_device_set_power(device, state);
 }
 EXPORT_SYMBOL(acpi_bus_set_power);
 
@@ -402,7 +417,7 @@ int acpi_bus_update_power(acpi_handle handle, int *state_p)
        if (result)
                return result;
 
-       result = __acpi_bus_set_power(device, state);
+       result = acpi_device_set_power(device, state);
        if (!result && state_p)
                *state_p = state;
 
index 1f9f7d7..811910b 100644 (file)
@@ -92,17 +92,24 @@ static int is_device_present(acpi_handle handle)
        return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
 }
 
+static bool 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 true;
+       }
+
+       return false;
+}
+
 /*******************************************************************/
 static int acpi_container_add(struct acpi_device *device)
 {
        struct acpi_container *container;
 
-
-       if (!device) {
-               printk(KERN_ERR PREFIX "device is NULL\n");
-               return -EINVAL;
-       }
-
        container = kzalloc(sizeof(struct acpi_container), GFP_KERNEL);
        if (!container)
                return -ENOMEM;
@@ -164,7 +171,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
        case ACPI_NOTIFY_BUS_CHECK:
                /* Fall through */
        case ACPI_NOTIFY_DEVICE_CHECK:
-               printk(KERN_WARNING "Container driver received %s event\n",
+               pr_debug("Container driver received %s event\n",
                       (type == ACPI_NOTIFY_BUS_CHECK) ?
                       "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK");
 
@@ -185,7 +192,7 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
 
                result = container_device_add(&device, handle);
                if (result) {
-                       printk(KERN_WARNING "Failed to add container\n");
+                       acpi_handle_warn(handle, "Failed to add container\n");
                        break;
                }
 
@@ -232,10 +239,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:
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
new file mode 100644 (file)
index 0000000..f09dc98
--- /dev/null
@@ -0,0 +1,668 @@
+/*
+ * drivers/acpi/device_pm.c - ACPI device power management routines.
+ *
+ * Copyright (C) 2012, Intel Corp.
+ * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.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.
+ *
+ *  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/device.h>
+#include <linux/export.h>
+#include <linux/mutex.h>
+#include <linux/pm_qos.h>
+#include <linux/pm_runtime.h>
+
+#include <acpi/acpi.h>
+#include <acpi/acpi_bus.h>
+
+static DEFINE_MUTEX(acpi_pm_notifier_lock);
+
+/**
+ * acpi_add_pm_notifier - Register PM notifier for given ACPI device.
+ * @adev: ACPI device to add the notifier for.
+ * @context: Context information to pass to the notifier routine.
+ *
+ * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of
+ * PM wakeup events.  For example, wakeup events may be generated for bridges
+ * if one of the devices below the bridge is signaling wakeup, even if the
+ * bridge itself doesn't have a wakeup GPE associated with it.
+ */
+acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
+                                acpi_notify_handler handler, void *context)
+{
+       acpi_status status = AE_ALREADY_EXISTS;
+
+       mutex_lock(&acpi_pm_notifier_lock);
+
+       if (adev->wakeup.flags.notifier_present)
+               goto out;
+
+       status = acpi_install_notify_handler(adev->handle,
+                                            ACPI_SYSTEM_NOTIFY,
+                                            handler, context);
+       if (ACPI_FAILURE(status))
+               goto out;
+
+       adev->wakeup.flags.notifier_present = true;
+
+ out:
+       mutex_unlock(&acpi_pm_notifier_lock);
+       return status;
+}
+
+/**
+ * acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device.
+ * @adev: ACPI device to remove the notifier from.
+ */
+acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
+                                   acpi_notify_handler handler)
+{
+       acpi_status status = AE_BAD_PARAMETER;
+
+       mutex_lock(&acpi_pm_notifier_lock);
+
+       if (!adev->wakeup.flags.notifier_present)
+               goto out;
+
+       status = acpi_remove_notify_handler(adev->handle,
+                                           ACPI_SYSTEM_NOTIFY,
+                                           handler);
+       if (ACPI_FAILURE(status))
+               goto out;
+
+       adev->wakeup.flags.notifier_present = false;
+
+ out:
+       mutex_unlock(&acpi_pm_notifier_lock);
+       return status;
+}
+
+/**
+ * acpi_device_power_state - Get preferred power state of ACPI device.
+ * @dev: Device whose preferred target power state to return.
+ * @adev: ACPI device node corresponding to @dev.
+ * @target_state: System state to match the resultant device state.
+ * @d_max_in: Deepest low-power state to take into consideration.
+ * @d_min_p: Location to store the upper limit of the allowed states range.
+ * 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 the
+ * device can be in while the system is in the state represented by
+ * @target_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.
+ *
+ * Callers must ensure that @dev and @adev are valid pointers and that @adev
+ * actually corresponds to @dev before using this function.
+ */
+int acpi_device_power_state(struct device *dev, struct acpi_device *adev,
+                           u32 target_state, int d_max_in, int *d_min_p)
+{
+       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;
+
+       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' + target_state;
+       /*
+        * If the sleep state is S0, the lowest limit from ACPI is D3,
+        * but if the device has _S0W, we will use the value from _S0W
+        * as the lowest limit from ACPI.  Finally, we will constrain
+        * the lowest limit with the specified one.
+        */
+       d_min = ACPI_STATE_D0;
+       d_max = ACPI_STATE_D3;
+
+       /*
+        * If present, _SxD methods return the minimum D-state (highest power
+        * state) we can use for the corresponding S-states.  Otherwise, the
+        * minimum D-state is D0 (ACPI 3.x).
+        *
+        * NOTE: We rely on acpi_evaluate_integer() not clobbering the integer
+        * provided -- that's our fault recovery, we ignore retval.
+        */
+       if (target_state > ACPI_STATE_S0) {
+               acpi_evaluate_integer(adev->handle, acpi_method, NULL, &d_min);
+               wakeup = device_may_wakeup(dev) && adev->wakeup.flags.valid
+                       && adev->wakeup.sleep_state >= target_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,
+        * the D-state returned by _SxD is sufficient for that (we assume a
+        * wakeup-aware driver if wake is set).  Still, if _SxW exists
+        * (ACPI 3.x), it should return the maximum (lowest power) D-state that
+        * can wake the system.  _S0W may be valid, too.
+        */
+       if (wakeup) {
+               acpi_status status;
+
+               acpi_method[3] = 'W';
+               status = acpi_evaluate_integer(adev->handle, acpi_method, NULL,
+                                               &d_max);
+               if (ACPI_FAILURE(status)) {
+                       if (target_state != ACPI_STATE_S0 ||
+                           status != AE_NOT_FOUND)
+                               d_max = d_min;
+               } else if (d_max < d_min) {
+                       /* Warn the user of the broken DSDT */
+                       printk(KERN_WARNING "ACPI: Wrong value from %s\n",
+                               acpi_method);
+                       /* Sanitize it */
+                       d_min = d_max;
+               }
+       }
+
+       if (d_max_in < d_min)
+               return -EINVAL;
+       if (d_min_p)
+               *d_min_p = d_min;
+       /* constrain d_max with specified lowest limit (max number) */
+       if (d_max > d_max_in) {
+               for (d_max = d_max_in; d_max > d_min; d_max--) {
+                       if (adev->power.states[d_max].flags.valid)
+                               break;
+               }
+       }
+       return d_max;
+}
+EXPORT_SYMBOL_GPL(acpi_device_power_state);
+
+/**
+ * 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
+ *
+ * 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;
+
+       if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
+               dev_dbg(dev, "ACPI handle without context in %s!\n", __func__);
+               return -ENODEV;
+       }
+
+       return acpi_device_power_state(dev, adev, acpi_target_system_state(),
+                                      d_max_in, d_min_p);
+}
+EXPORT_SYMBOL(acpi_pm_device_sleep_state);
+
+#ifdef CONFIG_PM_RUNTIME
+/**
+ * acpi_wakeup_device - Wakeup notification handler for ACPI devices.
+ * @handle: ACPI handle of the device the notification is for.
+ * @event: Type of the signaled event.
+ * @context: Device corresponding to @handle.
+ */
+static void acpi_wakeup_device(acpi_handle handle, u32 event, void *context)
+{
+       struct device *dev = context;
+
+       if (event == ACPI_NOTIFY_DEVICE_WAKE && dev) {
+               pm_wakeup_event(dev, 0);
+               pm_runtime_resume(dev);
+       }
+}
+
+/**
+ * __acpi_device_run_wake - Enable/disable runtime remote wakeup for device.
+ * @adev: ACPI device to enable/disable the remote wakeup for.
+ * @enable: Whether to enable or disable the wakeup functionality.
+ *
+ * Enable/disable the GPE associated with @adev so that it can generate
+ * wakeup signals for the device in response to external (remote) events and
+ * enable/disable device wakeup power.
+ *
+ * Callers must ensure that @adev is a valid ACPI device node before executing
+ * this function.
+ */
+int __acpi_device_run_wake(struct acpi_device *adev, bool enable)
+{
+       struct acpi_device_wakeup *wakeup = &adev->wakeup;
+
+       if (enable) {
+               acpi_status res;
+               int error;
+
+               error = acpi_enable_wakeup_device_power(adev, ACPI_STATE_S0);
+               if (error)
+                       return error;
+
+               res = acpi_enable_gpe(wakeup->gpe_device, wakeup->gpe_number);
+               if (ACPI_FAILURE(res)) {
+                       acpi_disable_wakeup_device_power(adev);
+                       return -EIO;
+               }
+       } else {
+               acpi_disable_gpe(wakeup->gpe_device, wakeup->gpe_number);
+               acpi_disable_wakeup_device_power(adev);
+       }
+       return 0;
+}
+
+/**
+ * acpi_pm_device_run_wake - Enable/disable remote wakeup for given device.
+ * @dev: Device to enable/disable the platform to wake up.
+ * @enable: Whether to enable or disable the wakeup functionality.
+ */
+int acpi_pm_device_run_wake(struct device *phys_dev, bool enable)
+{
+       struct acpi_device *adev;
+       acpi_handle handle;
+
+       if (!device_run_wake(phys_dev))
+               return -EINVAL;
+
+       handle = DEVICE_ACPI_HANDLE(phys_dev);
+       if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
+               dev_dbg(phys_dev, "ACPI handle without context in %s!\n",
+                       __func__);
+               return -ENODEV;
+       }
+
+       return __acpi_device_run_wake(adev, enable);
+}
+EXPORT_SYMBOL(acpi_pm_device_run_wake);
+#else
+static inline void acpi_wakeup_device(acpi_handle handle, u32 event,
+                                     void *context) {}
+#endif /* CONFIG_PM_RUNTIME */
+
+ #ifdef CONFIG_PM_SLEEP
+/**
+ * __acpi_device_sleep_wake - Enable or disable device to wake up the system.
+ * @dev: Device to enable/desible to wake up the system.
+ * @target_state: System state the device is supposed to wake up from.
+ * @enable: Whether to enable or disable @dev to wake up the system.
+ */
+int __acpi_device_sleep_wake(struct acpi_device *adev, u32 target_state,
+                            bool enable)
+{
+       return enable ?
+               acpi_enable_wakeup_device_power(adev, target_state) :
+               acpi_disable_wakeup_device_power(adev);
+}
+
+/**
+ * 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)
+{
+       acpi_handle handle;
+       struct acpi_device *adev;
+       int error;
+
+       if (!device_can_wakeup(dev))
+               return -EINVAL;
+
+       handle = DEVICE_ACPI_HANDLE(dev);
+       if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
+               dev_dbg(dev, "ACPI handle without context in %s!\n", __func__);
+               return -ENODEV;
+       }
+
+       error = __acpi_device_sleep_wake(adev, acpi_target_system_state(),
+                                        enable);
+       if (!error)
+               dev_info(dev, "System wakeup %s by ACPI\n",
+                               enable ? "enabled" : "disabled");
+
+       return error;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+/**
+ * acpi_dev_pm_get_node - Get ACPI device node for the given physical device.
+ * @dev: Device to get the ACPI node for.
+ */
+static struct acpi_device *acpi_dev_pm_get_node(struct device *dev)
+{
+       acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
+       struct acpi_device *adev;
+
+       return handle && ACPI_SUCCESS(acpi_bus_get_device(handle, &adev)) ?
+               adev : NULL;
+}
+
+/**
+ * acpi_dev_pm_low_power - Put ACPI device into a low-power state.
+ * @dev: Device to put into a low-power state.
+ * @adev: ACPI device node corresponding to @dev.
+ * @system_state: System state to choose the device state for.
+ */
+static int acpi_dev_pm_low_power(struct device *dev, struct acpi_device *adev,
+                                u32 system_state)
+{
+       int power_state;
+
+       if (!acpi_device_power_manageable(adev))
+               return 0;
+
+       power_state = acpi_device_power_state(dev, adev, system_state,
+                                             ACPI_STATE_D3, NULL);
+       if (power_state < ACPI_STATE_D0 || power_state > ACPI_STATE_D3)
+               return -EIO;
+
+       return acpi_device_set_power(adev, power_state);
+}
+
+/**
+ * acpi_dev_pm_full_power - Put ACPI device into the full-power state.
+ * @adev: ACPI device node to put into the full-power state.
+ */
+static int acpi_dev_pm_full_power(struct acpi_device *adev)
+{
+       return acpi_device_power_manageable(adev) ?
+               acpi_device_set_power(adev, ACPI_STATE_D0) : 0;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+/**
+ * acpi_dev_runtime_suspend - Put device into a low-power state using ACPI.
+ * @dev: Device to put into a low-power state.
+ *
+ * Put the given device into a runtime low-power state using the standard ACPI
+ * mechanism.  Set up remote wakeup if desired, choose the state to put the
+ * device into (this checks if remote wakeup is expected to work too), and set
+ * the power state of the device.
+ */
+int acpi_dev_runtime_suspend(struct device *dev)
+{
+       struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+       bool remote_wakeup;
+       int error;
+
+       if (!adev)
+               return 0;
+
+       remote_wakeup = dev_pm_qos_flags(dev, PM_QOS_FLAG_REMOTE_WAKEUP) >
+                               PM_QOS_FLAGS_NONE;
+       error = __acpi_device_run_wake(adev, remote_wakeup);
+       if (remote_wakeup && error)
+               return -EAGAIN;
+
+       error = acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0);
+       if (error)
+               __acpi_device_run_wake(adev, false);
+
+       return error;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_runtime_suspend);
+
+/**
+ * acpi_dev_runtime_resume - Put device into the full-power state using ACPI.
+ * @dev: Device to put into the full-power state.
+ *
+ * Put the given device into the full-power state using the standard ACPI
+ * mechanism at run time.  Set the power state of the device to ACPI D0 and
+ * disable remote wakeup.
+ */
+int acpi_dev_runtime_resume(struct device *dev)
+{
+       struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+       int error;
+
+       if (!adev)
+               return 0;
+
+       error = acpi_dev_pm_full_power(adev);
+       __acpi_device_run_wake(adev, false);
+       return error;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_runtime_resume);
+
+/**
+ * acpi_subsys_runtime_suspend - Suspend device using ACPI.
+ * @dev: Device to suspend.
+ *
+ * Carry out the generic runtime suspend procedure for @dev and use ACPI to put
+ * it into a runtime low-power state.
+ */
+int acpi_subsys_runtime_suspend(struct device *dev)
+{
+       int ret = pm_generic_runtime_suspend(dev);
+       return ret ? ret : acpi_dev_runtime_suspend(dev);
+}
+EXPORT_SYMBOL_GPL(acpi_subsys_runtime_suspend);
+
+/**
+ * acpi_subsys_runtime_resume - Resume device using ACPI.
+ * @dev: Device to Resume.
+ *
+ * Use ACPI to put the given device into the full-power state and carry out the
+ * generic runtime resume procedure for it.
+ */
+int acpi_subsys_runtime_resume(struct device *dev)
+{
+       int ret = acpi_dev_runtime_resume(dev);
+       return ret ? ret : pm_generic_runtime_resume(dev);
+}
+EXPORT_SYMBOL_GPL(acpi_subsys_runtime_resume);
+#endif /* CONFIG_PM_RUNTIME */
+
+#ifdef CONFIG_PM_SLEEP
+/**
+ * acpi_dev_suspend_late - Put device into a low-power state using ACPI.
+ * @dev: Device to put into a low-power state.
+ *
+ * Put the given device into a low-power state during system transition to a
+ * sleep state using the standard ACPI mechanism.  Set up system wakeup if
+ * desired, choose the state to put the device into (this checks if system
+ * wakeup is expected to work too), and set the power state of the device.
+ */
+int acpi_dev_suspend_late(struct device *dev)
+{
+       struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+       u32 target_state;
+       bool wakeup;
+       int error;
+
+       if (!adev)
+               return 0;
+
+       target_state = acpi_target_system_state();
+       wakeup = device_may_wakeup(dev);
+       error = __acpi_device_sleep_wake(adev, target_state, wakeup);
+       if (wakeup && error)
+               return error;
+
+       error = acpi_dev_pm_low_power(dev, adev, target_state);
+       if (error)
+               __acpi_device_sleep_wake(adev, ACPI_STATE_UNKNOWN, false);
+
+       return error;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_suspend_late);
+
+/**
+ * acpi_dev_resume_early - Put device into the full-power state using ACPI.
+ * @dev: Device to put into the full-power state.
+ *
+ * Put the given device into the full-power state using the standard ACPI
+ * mechanism during system transition to the working state.  Set the power
+ * state of the device to ACPI D0 and disable remote wakeup.
+ */
+int acpi_dev_resume_early(struct device *dev)
+{
+       struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+       int error;
+
+       if (!adev)
+               return 0;
+
+       error = acpi_dev_pm_full_power(adev);
+       __acpi_device_sleep_wake(adev, ACPI_STATE_UNKNOWN, false);
+       return error;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_resume_early);
+
+/**
+ * acpi_subsys_prepare - Prepare device for system transition to a sleep state.
+ * @dev: Device to prepare.
+ */
+int acpi_subsys_prepare(struct device *dev)
+{
+       /*
+        * Follow PCI and resume devices suspended at run time before running
+        * their system suspend callbacks.
+        */
+       pm_runtime_resume(dev);
+       return pm_generic_prepare(dev);
+}
+EXPORT_SYMBOL_GPL(acpi_subsys_prepare);
+
+/**
+ * acpi_subsys_suspend_late - Suspend device using ACPI.
+ * @dev: Device to suspend.
+ *
+ * Carry out the generic late suspend procedure for @dev and use ACPI to put
+ * it into a low-power state during system transition into a sleep state.
+ */
+int acpi_subsys_suspend_late(struct device *dev)
+{
+       int ret = pm_generic_suspend_late(dev);
+       return ret ? ret : acpi_dev_suspend_late(dev);
+}
+EXPORT_SYMBOL_GPL(acpi_subsys_suspend_late);
+
+/**
+ * acpi_subsys_resume_early - Resume device using ACPI.
+ * @dev: Device to Resume.
+ *
+ * Use ACPI to put the given device into the full-power state and carry out the
+ * generic early resume procedure for it during system transition into the
+ * working state.
+ */
+int acpi_subsys_resume_early(struct device *dev)
+{
+       int ret = acpi_dev_resume_early(dev);
+       return ret ? ret : pm_generic_resume_early(dev);
+}
+EXPORT_SYMBOL_GPL(acpi_subsys_resume_early);
+#endif /* CONFIG_PM_SLEEP */
+
+static struct dev_pm_domain acpi_general_pm_domain = {
+       .ops = {
+#ifdef CONFIG_PM_RUNTIME
+               .runtime_suspend = acpi_subsys_runtime_suspend,
+               .runtime_resume = acpi_subsys_runtime_resume,
+               .runtime_idle = pm_generic_runtime_idle,
+#endif
+#ifdef CONFIG_PM_SLEEP
+               .prepare = acpi_subsys_prepare,
+               .suspend_late = acpi_subsys_suspend_late,
+               .resume_early = acpi_subsys_resume_early,
+               .poweroff_late = acpi_subsys_suspend_late,
+               .restore_early = acpi_subsys_resume_early,
+#endif
+       },
+};
+
+/**
+ * acpi_dev_pm_attach - Prepare device for ACPI power management.
+ * @dev: Device to prepare.
+ * @power_on: Whether or not to power on the device.
+ *
+ * If @dev has a valid ACPI handle that has a valid struct acpi_device object
+ * attached to it, install a wakeup notification handler for the device and
+ * add it to the general ACPI PM domain.  If @power_on is set, the device will
+ * be put into the ACPI D0 state before the function returns.
+ *
+ * This assumes that the @dev's bus type uses generic power management callbacks
+ * (or doesn't use any power management callbacks at all).
+ *
+ * Callers must ensure proper synchronization of this function with power
+ * management callbacks.
+ */
+int acpi_dev_pm_attach(struct device *dev, bool power_on)
+{
+       struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+
+       if (!adev)
+               return -ENODEV;
+
+       if (dev->pm_domain)
+               return -EEXIST;
+
+       acpi_add_pm_notifier(adev, acpi_wakeup_device, dev);
+       dev->pm_domain = &acpi_general_pm_domain;
+       if (power_on) {
+               acpi_dev_pm_full_power(adev);
+               __acpi_device_run_wake(adev, false);
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_pm_attach);
+
+/**
+ * acpi_dev_pm_detach - Remove ACPI power management from the device.
+ * @dev: Device to take care of.
+ * @power_off: Whether or not to try to remove power from the device.
+ *
+ * Remove the device from the general ACPI PM domain and remove its wakeup
+ * notifier.  If @power_off is set, additionally remove power from the device if
+ * possible.
+ *
+ * Callers must ensure proper synchronization of this function with power
+ * management callbacks.
+ */
+void acpi_dev_pm_detach(struct device *dev, bool power_off)
+{
+       struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+
+       if (adev && dev->pm_domain == &acpi_general_pm_domain) {
+               dev->pm_domain = NULL;
+               acpi_remove_pm_notifier(adev, acpi_wakeup_device);
+               if (power_off) {
+                       /*
+                        * If the device's PM QoS resume latency limit or flags
+                        * have been exposed to user space, they have to be
+                        * hidden at this point, so that they don't affect the
+                        * choice of the low-power state to put the device into.
+                        */
+                       dev_pm_qos_hide_latency_limit(dev);
+                       dev_pm_qos_hide_flags(dev);
+                       __acpi_device_run_wake(adev, false);
+                       acpi_dev_pm_low_power(dev, adev, ACPI_STATE_S0);
+               }
+       }
+}
+EXPORT_SYMBOL_GPL(acpi_dev_pm_detach);
index 88eb143..f32bd47 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/platform_device.h>
 #include <linux/jiffies.h>
 #include <linux/stddef.h>
+#include <linux/acpi.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
@@ -460,12 +461,8 @@ static void handle_dock(struct dock_station *ds, int dock)
        struct acpi_object_list arg_list;
        union acpi_object arg;
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-       struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 
-       acpi_get_name(ds->handle, ACPI_FULL_PATHNAME, &name_buffer);
-
-       printk(KERN_INFO PREFIX "%s - %s\n",
-               (char *)name_buffer.pointer, dock ? "docking" : "undocking");
+       acpi_handle_info(ds->handle, "%s\n", dock ? "docking" : "undocking");
 
        /* _DCK method has one argument */
        arg_list.count = 1;
@@ -474,11 +471,10 @@ static void handle_dock(struct dock_station *ds, int dock)
        arg.integer.value = dock;
        status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer);
        if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
-               ACPI_EXCEPTION((AE_INFO, status, "%s - failed to execute"
-                       " _DCK\n", (char *)name_buffer.pointer));
+               acpi_handle_err(ds->handle, "Failed to execute _DCK (0x%x)\n",
+                               status);
 
        kfree(buffer.pointer);
-       kfree(name_buffer.pointer);
 }
 
 static inline void dock(struct dock_station *ds)
@@ -525,9 +521,11 @@ static void dock_lock(struct dock_station *ds, int lock)
        status = acpi_evaluate_object(ds->handle, "_LCK", &arg_list, NULL);
        if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
                if (lock)
-                       printk(KERN_WARNING PREFIX "Locking device failed\n");
+                       acpi_handle_warn(ds->handle,
+                               "Locking device failed (0x%x)\n", status);
                else
-                       printk(KERN_WARNING PREFIX "Unlocking device failed\n");
+                       acpi_handle_warn(ds->handle,
+                               "Unlocking device failed (0x%x)\n", status);
        }
 }
 
@@ -667,7 +665,7 @@ static int handle_eject_request(struct dock_station *ds, u32 event)
        dock_lock(ds, 0);
        eject_dock(ds);
        if (dock_present(ds)) {
-               printk(KERN_ERR PREFIX "Unable to undock!\n");
+               acpi_handle_err(ds->handle, "Unable to undock!\n");
                return -EBUSY;
        }
        complete_undock(ds);
@@ -715,7 +713,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
                        begin_dock(ds);
                        dock(ds);
                        if (!dock_present(ds)) {
-                               printk(KERN_ERR PREFIX "Unable to dock!\n");
+                               acpi_handle_err(handle, "Unable to dock!\n");
                                complete_dock(ds);
                                break;
                        }
@@ -743,7 +741,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
                        dock_event(ds, event, UNDOCK_EVENT);
                break;
        default:
-               printk(KERN_ERR PREFIX "Unknown dock event %d\n", event);
+               acpi_handle_err(handle, "Unknown dock event %d\n", event);
        }
 }
 
@@ -987,7 +985,7 @@ err_rmgroup:
        sysfs_remove_group(&dd->dev.kobj, &dock_attribute_group);
 err_unregister:
        platform_device_unregister(dd);
-       printk(KERN_ERR "%s encountered error %d\n", __func__, ret);
+       acpi_handle_err(handle, "%s encountered error %d\n", __func__, ret);
        return ret;
 }
 
@@ -1016,51 +1014,39 @@ 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");
+               pr_info(PREFIX "No dock devices found.\n");
                return 0;
        }
 
        register_acpi_bus_notifier(&dock_acpi_notifier);
-       printk(KERN_INFO PREFIX "%s: %d docks/bays found\n",
+       pr_info(PREFIX "%s: %d docks/bays found\n",
                ACPI_DOCK_DRIVER_DESCRIPTION, dock_station_count);
        return 0;
 }
index a51df96..354007d 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 d1a2d74..0155184 100644 (file)
@@ -130,45 +130,59 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
 {
        struct acpi_device *acpi_dev;
        acpi_status status;
-       struct acpi_device_physical_node *physical_node;
+       struct acpi_device_physical_node *physical_node, *pn;
        char physical_node_name[sizeof(PHYSICAL_NODE_STRING) + 2];
        int retval = -EINVAL;
 
-       if (dev->archdata.acpi_handle) {
-               dev_warn(dev, "Drivers changed 'acpi_handle'\n");
-               return -EINVAL;
+       if (ACPI_HANDLE(dev)) {
+               if (handle) {
+                       dev_warn(dev, "ACPI handle is already set\n");
+                       return -EINVAL;
+               } else {
+                       handle = ACPI_HANDLE(dev);
+               }
        }
+       if (!handle)
+               return -EINVAL;
 
        get_device(dev);
        status = acpi_bus_get_device(handle, &acpi_dev);
        if (ACPI_FAILURE(status))
                goto err;
 
-       physical_node = kzalloc(sizeof(struct acpi_device_physical_node),
-               GFP_KERNEL);
+       physical_node = kzalloc(sizeof(*physical_node), GFP_KERNEL);
        if (!physical_node) {
                retval = -ENOMEM;
                goto err;
        }
 
        mutex_lock(&acpi_dev->physical_node_lock);
+
+       /* Sanity check. */
+       list_for_each_entry(pn, &acpi_dev->physical_node_list, node)
+               if (pn->dev == dev) {
+                       dev_warn(dev, "Already associated with ACPI node\n");
+                       goto err_free;
+               }
+
        /* allocate physical node id according to physical_node_id_bitmap */
        physical_node->node_id =
                find_first_zero_bit(acpi_dev->physical_node_id_bitmap,
                ACPI_MAX_PHYSICAL_NODE);
        if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) {
                retval = -ENOSPC;
-               mutex_unlock(&acpi_dev->physical_node_lock);
-               goto err;
+               goto err_free;
        }
 
        set_bit(physical_node->node_id, acpi_dev->physical_node_id_bitmap);
        physical_node->dev = dev;
        list_add_tail(&physical_node->node, &acpi_dev->physical_node_list);
        acpi_dev->physical_node_count++;
+
        mutex_unlock(&acpi_dev->physical_node_lock);
 
-       dev->archdata.acpi_handle = handle;
+       if (!ACPI_HANDLE(dev))
+               ACPI_HANDLE_SET(dev, acpi_dev->handle);
 
        if (!physical_node->node_id)
                strcpy(physical_node_name, PHYSICAL_NODE_STRING);
@@ -186,8 +200,14 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
        return 0;
 
  err:
+       ACPI_HANDLE_SET(dev, NULL);
        put_device(dev);
        return retval;
+
+ err_free:
+       mutex_unlock(&acpi_dev->physical_node_lock);
+       kfree(physical_node);
+       goto err;
 }
 
 static int acpi_unbind_one(struct device *dev)
@@ -197,11 +217,10 @@ static int acpi_unbind_one(struct device *dev)
        acpi_status status;
        struct list_head *node, *next;
 
-       if (!dev->archdata.acpi_handle)
+       if (!ACPI_HANDLE(dev))
                return 0;
 
-       status = acpi_bus_get_device(dev->archdata.acpi_handle,
-               &acpi_dev);
+       status = acpi_bus_get_device(ACPI_HANDLE(dev), &acpi_dev);
        if (ACPI_FAILURE(status))
                goto err;
 
@@ -227,7 +246,7 @@ static int acpi_unbind_one(struct device *dev)
 
                sysfs_remove_link(&acpi_dev->dev.kobj, physical_node_name);
                sysfs_remove_link(&dev->kobj, "firmware_node");
-               dev->archdata.acpi_handle = NULL;
+               ACPI_HANDLE_SET(dev, NULL);
                /* acpi_bind_one increase refcnt by one */
                put_device(dev);
                kfree(entry);
@@ -247,6 +266,10 @@ static int acpi_platform_notify(struct device *dev)
        acpi_handle handle;
        int ret = -EINVAL;
 
+       ret = acpi_bind_one(dev, NULL);
+       if (!ret)
+               goto out;
+
        if (!dev->bus || !dev->parent) {
                /* bridge devices genernally haven't bus or parent */
                ret = acpi_find_bridge_device(dev, &handle);
@@ -260,16 +283,16 @@ static int acpi_platform_notify(struct device *dev)
        }
        if ((ret = type->find_device(dev, &handle)) != 0)
                DBG("Can't get handler for %s\n", dev_name(dev));
     end:
+ end:
        if (!ret)
                acpi_bind_one(dev, handle);
 
+ out:
 #if ACPI_GLUE_DEBUG
        if (!ret) {
                struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 
-               acpi_get_name(dev->archdata.acpi_handle,
-                             ACPI_FULL_PATHNAME, &buffer);
+               acpi_get_name(dev->acpi_handle, ACPI_FULL_PATHNAME, &buffer);
                DBG("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer);
                kfree(buffer.pointer);
        } else
index 20a0f2c..b514e81 100644 (file)
@@ -70,7 +70,7 @@ static int __devinit acpi_hed_add(struct acpi_device *device)
        return 0;
 }
 
-static int __devexit acpi_hed_remove(struct acpi_device *device, int type)
+static int acpi_hed_remove(struct acpi_device *device, int type)
 {
        hed_handle = NULL;
        return 0;
index ca75b9c..3c407cd 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;
@@ -93,4 +93,11 @@ static inline int suspend_nvs_save(void) { return 0; }
 static inline void suspend_nvs_restore(void) {}
 #endif
 
+/*--------------------------------------------------------------------------
+                               Platform bus support
+  -------------------------------------------------------------------------- */
+struct platform_device;
+
+struct platform_device *acpi_create_platform_device(struct acpi_device *adev);
+
 #endif /* _ACPI_INTERNAL_H_ */
index 9eaf708..6dc4a2b 100644 (file)
@@ -932,7 +932,7 @@ static acpi_status __acpi_os_execute(acpi_execute_type type,
         * having a static work_struct.
         */
 
-       dpc = kmalloc(sizeof(struct acpi_os_dpc), GFP_ATOMIC);
+       dpc = kzalloc(sizeof(struct acpi_os_dpc), GFP_ATOMIC);
        if (!dpc)
                return AE_NO_MEMORY;
 
@@ -944,17 +944,22 @@ static acpi_status __acpi_os_execute(acpi_execute_type type,
         * because the hotplug code may call driver .remove() functions,
         * which invoke flush_scheduled_work/acpi_os_wait_events_complete
         * to flush these workqueues.
+        *
+        * To prevent lockdep from complaining unnecessarily, make sure that
+        * there is a different static lockdep key for each workqueue by using
+        * INIT_WORK() for each of them separately.
         */
-       queue = hp ? kacpi_hotplug_wq :
-               (type == OSL_NOTIFY_HANDLER ? kacpi_notify_wq : kacpid_wq);
-       dpc->wait = hp ? 1 : 0;
-
-       if (queue == kacpi_hotplug_wq)
+       if (hp) {
+               queue = kacpi_hotplug_wq;
+               dpc->wait = 1;
                INIT_WORK(&dpc->work, acpi_os_execute_deferred);
-       else if (queue == kacpi_notify_wq)
+       } else if (type == OSL_NOTIFY_HANDLER) {
+               queue = kacpi_notify_wq;
                INIT_WORK(&dpc->work, acpi_os_execute_deferred);
-       else
+       } else {
+               queue = kacpid_wq;
                INIT_WORK(&dpc->work, acpi_os_execute_deferred);
+       }
 
        /*
         * On some machines, a software-initiated SMI causes corruption unless
@@ -986,6 +991,7 @@ acpi_status acpi_os_hotplug_execute(acpi_osd_exec_callback function,
 {
        return __acpi_os_execute(0, function, context, 1);
 }
+EXPORT_SYMBOL(acpi_os_hotplug_execute);
 
 void acpi_os_wait_events_complete(void)
 {
index 0eefa12..23a0324 100644 (file)
@@ -459,19 +459,19 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
         */
        if (gsi < 0) {
                u32 dev_gsi;
-               dev_warn(&dev->dev, "PCI INT %c: no GSI", pin_name(pin));
                /* Interrupt Line values above 0xF are forbidden */
                if (dev->irq > 0 && (dev->irq <= 0xF) &&
                    (acpi_isa_irq_to_gsi(dev->irq, &dev_gsi) == 0)) {
-                       printk(" - using ISA IRQ %d\n", dev->irq);
+                       dev_warn(&dev->dev, "PCI INT %c: no GSI - using ISA IRQ %d\n",
+                                pin_name(pin), dev->irq);
                        acpi_register_gsi(&dev->dev, dev_gsi,
                                          ACPI_LEVEL_SENSITIVE,
                                          ACPI_ACTIVE_LOW);
-                       return 0;
                } else {
-                       printk("\n");
-                       return 0;
+                       dev_warn(&dev->dev, "PCI INT %c: no GSI\n",
+                                pin_name(pin));
                }
+               return 0;
        }
 
        rc = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
@@ -495,11 +495,6 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
        return 0;
 }
 
-/* FIXME: implement x86/x86_64 version */
-void __attribute__ ((weak)) acpi_unregister_gsi(u32 i)
-{
-}
-
 void acpi_pci_irq_disable(struct pci_dev *dev)
 {
        struct acpi_prt_entry *entry;
index 40e38a0..7db61b8 100644 (file)
@@ -473,7 +473,7 @@ int acpi_power_resource_register_device(struct device *dev, acpi_handle handle)
        return ret;
 
 no_power_resource:
-       printk(KERN_DEBUG PREFIX "Invalid Power Resource to register!");
+       printk(KERN_DEBUG PREFIX "Invalid Power Resource to register!\n");
        return -ENODEV;
 }
 EXPORT_SYMBOL_GPL(acpi_power_resource_register_device);
index 27adb09..ef98796 100644 (file)
@@ -362,16 +362,13 @@ acpi_system_write_wakeup_device(struct file *file,
        struct list_head *node, *next;
        char strbuf[5];
        char str[5] = "";
-       unsigned int len = count;
 
-       if (len > 4)
-               len = 4;
-       if (len < 0)
-               return -EFAULT;
+       if (count > 4)
+               count = 4;
 
-       if (copy_from_user(strbuf, buffer, len))
+       if (copy_from_user(strbuf, buffer, count))
                return -EFAULT;
-       strbuf[len] = '\0';
+       strbuf[count] = '\0';
        sscanf(strbuf, "%s", str);
 
        mutex_lock(&acpi_device_lock);
index e78c2a5..e83311b 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/moduleparam.h>
 #include <linux/cpuidle.h>
 #include <linux/slab.h>
+#include <linux/acpi.h>
 
 #include <asm/io.h>
 #include <asm/cpu.h>
@@ -282,7 +283,9 @@ static int acpi_processor_get_info(struct acpi_device *device)
                /* Declared with "Processor" statement; match ProcessorID */
                status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer);
                if (ACPI_FAILURE(status)) {
-                       printk(KERN_ERR PREFIX "Evaluating processor object\n");
+                       dev_err(&device->dev,
+                               "Failed to evaluate processor object (0x%x)\n",
+                               status);
                        return -ENODEV;
                }
 
@@ -301,8 +304,9 @@ static int acpi_processor_get_info(struct acpi_device *device)
                status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID,
                                                NULL, &value);
                if (ACPI_FAILURE(status)) {
-                       printk(KERN_ERR PREFIX
-                           "Evaluating processor _UID [%#x]\n", status);
+                       dev_err(&device->dev,
+                               "Failed to evaluate processor _UID (0x%x)\n",
+                               status);
                        return -ENODEV;
                }
                device_declaration = 1;
@@ -345,7 +349,7 @@ static int acpi_processor_get_info(struct acpi_device *device)
        if (!object.processor.pblk_address)
                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n"));
        else if (object.processor.pblk_length != 6)
-               printk(KERN_ERR PREFIX "Invalid PBLK length [%d]\n",
+               dev_err(&device->dev, "Invalid PBLK length [%d]\n",
                            object.processor.pblk_length);
        else {
                pr->throttling.address = object.processor.pblk_address;
@@ -409,6 +413,7 @@ static void acpi_processor_notify(struct acpi_device *device, u32 event)
                acpi_bus_generate_proc_event(device, event, 0);
                acpi_bus_generate_netlink_event(device->pnp.device_class,
                                                  dev_name(&device->dev), event, 0);
+               break;
        default:
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                  "Unsupported event [0x%x]\n", event));
@@ -429,8 +434,8 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb,
                 * Initialize missing things
                 */
                if (pr->flags.need_hotplug_init) {
-                       printk(KERN_INFO "Will online and init hotplugged "
-                              "CPU: %d\n", pr->id);
+                       pr_info("Will online and init hotplugged CPU: %d\n",
+                               pr->id);
                        WARN(acpi_processor_start(pr), "Failed to start CPU:"
                                " %d\n", pr->id);
                        pr->flags.need_hotplug_init = 0;
@@ -491,14 +496,16 @@ static __ref int acpi_processor_start(struct acpi_processor *pr)
                                   &pr->cdev->device.kobj,
                                   "thermal_cooling");
        if (result) {
-               printk(KERN_ERR PREFIX "Create sysfs link\n");
+               dev_err(&device->dev,
+                       "Failed to create sysfs link 'thermal_cooling'\n");
                goto err_thermal_unregister;
        }
        result = sysfs_create_link(&pr->cdev->device.kobj,
                                   &device->dev.kobj,
                                   "device");
        if (result) {
-               printk(KERN_ERR PREFIX "Create sysfs link\n");
+               dev_err(&pr->cdev->device,
+                       "Failed to create sysfs link 'device'\n");
                goto err_remove_sysfs_thermal;
        }
 
@@ -560,8 +567,9 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
         */
        if (per_cpu(processor_device_array, pr->id) != NULL &&
            per_cpu(processor_device_array, pr->id) != device) {
-               printk(KERN_WARNING "BIOS reported wrong ACPI id "
-                       "for the processor\n");
+               dev_warn(&device->dev,
+                       "BIOS reported wrong ACPI id %d for the processor\n",
+                       pr->id);
                result = -ENODEV;
                goto err_free_cpumask;
        }
@@ -694,8 +702,8 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
 static void acpi_processor_hotplug_notify(acpi_handle handle,
                                          u32 event, void *data)
 {
-       struct acpi_processor *pr;
        struct acpi_device *device = NULL;
+       struct acpi_eject_event *ej_event = NULL;
        u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
        int result;
 
@@ -715,7 +723,7 @@ static void acpi_processor_hotplug_notify(acpi_handle handle,
 
                result = acpi_processor_device_add(handle, &device);
                if (result) {
-                       printk(KERN_ERR PREFIX "Unable to add the device\n");
+                       acpi_handle_err(handle, "Unable to add the device\n");
                        break;
                }
 
@@ -727,20 +735,29 @@ static void acpi_processor_hotplug_notify(acpi_handle handle,
                                  "received ACPI_NOTIFY_EJECT_REQUEST\n"));
 
                if (acpi_bus_get_device(handle, &device)) {
-                       printk(KERN_ERR PREFIX
-                                   "Device don't exist, dropping EJECT\n");
+                       acpi_handle_err(handle,
+                               "Device don't exist, dropping EJECT\n");
                        break;
                }
-               pr = acpi_driver_data(device);
-               if (!pr) {
-                       printk(KERN_ERR PREFIX
-                                   "Driver data is NULL, dropping EJECT\n");
+               if (!acpi_driver_data(device)) {
+                       acpi_handle_err(handle,
+                               "Driver data is NULL, dropping EJECT\n");
                        break;
                }
 
-               /* REVISIT: update when eject is supported */
-               ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED;
-               break;
+               ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
+               if (!ej_event) {
+                       acpi_handle_err(handle, "No memory, dropping EJECT\n");
+                       break;
+               }
+
+               ej_event->handle = handle;
+               ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
+               acpi_os_hotplug_execute(acpi_bus_hot_remove_device,
+                                       (void *)ej_event);
+
+               /* eject is performed asynchronously */
+               return;
 
        default:
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -840,7 +857,7 @@ static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr)
         * and do it when the CPU gets online the first time
         * TBD: Cleanup above functions and try to do this more elegant.
         */
-       printk(KERN_INFO "CPU %d got hotplugged\n", pr->id);
+       pr_info("CPU %d got hotplugged\n", pr->id);
        pr->flags.need_hotplug_init = 1;
 
        return AE_OK;
@@ -851,8 +868,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 e8086c7..f1a5da4 100644 (file)
@@ -735,31 +735,18 @@ static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx)
 static int acpi_idle_enter_c1(struct cpuidle_device *dev,
                struct cpuidle_driver *drv, int index)
 {
-       ktime_t  kt1, kt2;
-       s64 idle_time;
        struct acpi_processor *pr;
        struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
        struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
 
        pr = __this_cpu_read(processors);
-       dev->last_residency = 0;
 
        if (unlikely(!pr))
                return -EINVAL;
 
-       local_irq_disable();
-
-
        lapic_timer_state_broadcast(pr, cx, 1);
-       kt1 = ktime_get_real();
        acpi_idle_do_entry(cx);
-       kt2 = ktime_get_real();
-       idle_time =  ktime_to_us(ktime_sub(kt2, kt1));
-
-       /* Update device last_residency*/
-       dev->last_residency = (int)idle_time;
 
-       local_irq_enable();
        lapic_timer_state_broadcast(pr, cx, 0);
 
        return index;
@@ -806,19 +793,12 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
        struct acpi_processor *pr;
        struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
        struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
-       ktime_t  kt1, kt2;
-       s64 idle_time_ns;
-       s64 idle_time;
 
        pr = __this_cpu_read(processors);
-       dev->last_residency = 0;
 
        if (unlikely(!pr))
                return -EINVAL;
 
-       local_irq_disable();
-
-
        if (cx->entry_method != ACPI_CSTATE_FFH) {
                current_thread_info()->status &= ~TS_POLLING;
                /*
@@ -829,7 +809,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
 
                if (unlikely(need_resched())) {
                        current_thread_info()->status |= TS_POLLING;
-                       local_irq_enable();
                        return -EINVAL;
                }
        }
@@ -843,22 +822,12 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
        if (cx->type == ACPI_STATE_C3)
                ACPI_FLUSH_CPU_CACHE();
 
-       kt1 = ktime_get_real();
        /* Tell the scheduler that we are going deep-idle: */
        sched_clock_idle_sleep_event();
        acpi_idle_do_entry(cx);
-       kt2 = ktime_get_real();
-       idle_time_ns = ktime_to_ns(ktime_sub(kt2, kt1));
-       idle_time = idle_time_ns;
-       do_div(idle_time, NSEC_PER_USEC);
 
-       /* Update device last_residency*/
-       dev->last_residency = (int)idle_time;
+       sched_clock_idle_wakeup_event(0);
 
-       /* Tell the scheduler how much we idled: */
-       sched_clock_idle_wakeup_event(idle_time_ns);
-
-       local_irq_enable();
        if (cx->entry_method != ACPI_CSTATE_FFH)
                current_thread_info()->status |= TS_POLLING;
 
@@ -883,13 +852,8 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
        struct acpi_processor *pr;
        struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
        struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage);
-       ktime_t  kt1, kt2;
-       s64 idle_time_ns;
-       s64 idle_time;
-
 
        pr = __this_cpu_read(processors);
-       dev->last_residency = 0;
 
        if (unlikely(!pr))
                return -EINVAL;
@@ -899,16 +863,11 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
                        return drv->states[drv->safe_state_index].enter(dev,
                                                drv, drv->safe_state_index);
                } else {
-                       local_irq_disable();
                        acpi_safe_halt();
-                       local_irq_enable();
                        return -EBUSY;
                }
        }
 
-       local_irq_disable();
-
-
        if (cx->entry_method != ACPI_CSTATE_FFH) {
                current_thread_info()->status &= ~TS_POLLING;
                /*
@@ -919,7 +878,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
 
                if (unlikely(need_resched())) {
                        current_thread_info()->status |= TS_POLLING;
-                       local_irq_enable();
                        return -EINVAL;
                }
        }
@@ -934,7 +892,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
         */
        lapic_timer_state_broadcast(pr, cx, 1);
 
-       kt1 = ktime_get_real();
        /*
         * disable bus master
         * bm_check implies we need ARB_DIS
@@ -965,18 +922,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
                c3_cpu_count--;
                raw_spin_unlock(&c3_lock);
        }
-       kt2 = ktime_get_real();
-       idle_time_ns = ktime_to_ns(ktime_sub(kt2, kt1));
-       idle_time = idle_time_ns;
-       do_div(idle_time, NSEC_PER_USEC);
-
-       /* Update device last_residency*/
-       dev->last_residency = (int)idle_time;
 
-       /* Tell the scheduler how much we idled: */
-       sched_clock_idle_wakeup_event(idle_time_ns);
+       sched_clock_idle_wakeup_event(0);
 
-       local_irq_enable();
        if (cx->entry_method != ACPI_CSTATE_FFH)
                current_thread_info()->status |= TS_POLLING;
 
@@ -987,6 +935,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
 struct cpuidle_driver acpi_idle_driver = {
        .name =         "acpi_idle",
        .owner =        THIS_MODULE,
+       .en_core_tk_irqen = 1,
 };
 
 /**
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
new file mode 100644 (file)
index 0000000..a3868f6
--- /dev/null
@@ -0,0 +1,526 @@
+/*
+ * drivers/acpi/resource.c - ACPI device resources interpretation.
+ *
+ * Copyright (C) 2012, Intel Corp.
+ * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.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.
+ *
+ *  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/acpi.h>
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+
+#ifdef CONFIG_X86
+#define valid_IRQ(i) (((i) != 0) && ((i) != 2))
+#else
+#define valid_IRQ(i) (true)
+#endif
+
+static unsigned long acpi_dev_memresource_flags(u64 len, u8 write_protect,
+                                               bool window)
+{
+       unsigned long flags = IORESOURCE_MEM;
+
+       if (len == 0)
+               flags |= IORESOURCE_DISABLED;
+
+       if (write_protect == ACPI_READ_WRITE_MEMORY)
+               flags |= IORESOURCE_MEM_WRITEABLE;
+
+       if (window)
+               flags |= IORESOURCE_WINDOW;
+
+       return flags;
+}
+
+static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len,
+                                    u8 write_protect)
+{
+       res->start = start;
+       res->end = start + len - 1;
+       res->flags = acpi_dev_memresource_flags(len, write_protect, false);
+}
+
+/**
+ * acpi_dev_resource_memory - Extract ACPI memory resource information.
+ * @ares: Input ACPI resource object.
+ * @res: Output generic resource object.
+ *
+ * Check if the given ACPI resource object represents a memory resource and
+ * if that's the case, use the information in it to populate the generic
+ * resource object pointed to by @res.
+ */
+bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res)
+{
+       struct acpi_resource_memory24 *memory24;
+       struct acpi_resource_memory32 *memory32;
+       struct acpi_resource_fixed_memory32 *fixed_memory32;
+
+       switch (ares->type) {
+       case ACPI_RESOURCE_TYPE_MEMORY24:
+               memory24 = &ares->data.memory24;
+               acpi_dev_get_memresource(res, memory24->minimum,
+                                        memory24->address_length,
+                                        memory24->write_protect);
+               break;
+       case ACPI_RESOURCE_TYPE_MEMORY32:
+               memory32 = &ares->data.memory32;
+               acpi_dev_get_memresource(res, memory32->minimum,
+                                        memory32->address_length,
+                                        memory32->write_protect);
+               break;
+       case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+               fixed_memory32 = &ares->data.fixed_memory32;
+               acpi_dev_get_memresource(res, fixed_memory32->address,
+                                        fixed_memory32->address_length,
+                                        fixed_memory32->write_protect);
+               break;
+       default:
+               return false;
+       }
+       return true;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_resource_memory);
+
+static unsigned int acpi_dev_ioresource_flags(u64 start, u64 end, u8 io_decode,
+                                             bool window)
+{
+       int flags = IORESOURCE_IO;
+
+       if (io_decode == ACPI_DECODE_16)
+               flags |= IORESOURCE_IO_16BIT_ADDR;
+
+       if (start > end || end >= 0x10003)
+               flags |= IORESOURCE_DISABLED;
+
+       if (window)
+               flags |= IORESOURCE_WINDOW;
+
+       return flags;
+}
+
+static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len,
+                                   u8 io_decode)
+{
+       u64 end = start + len - 1;
+
+       res->start = start;
+       res->end = end;
+       res->flags = acpi_dev_ioresource_flags(start, end, io_decode, false);
+}
+
+/**
+ * acpi_dev_resource_io - Extract ACPI I/O resource information.
+ * @ares: Input ACPI resource object.
+ * @res: Output generic resource object.
+ *
+ * Check if the given ACPI resource object represents an I/O resource and
+ * if that's the case, use the information in it to populate the generic
+ * resource object pointed to by @res.
+ */
+bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res)
+{
+       struct acpi_resource_io *io;
+       struct acpi_resource_fixed_io *fixed_io;
+
+       switch (ares->type) {
+       case ACPI_RESOURCE_TYPE_IO:
+               io = &ares->data.io;
+               acpi_dev_get_ioresource(res, io->minimum,
+                                       io->address_length,
+                                       io->io_decode);
+               break;
+       case ACPI_RESOURCE_TYPE_FIXED_IO:
+               fixed_io = &ares->data.fixed_io;
+               acpi_dev_get_ioresource(res, fixed_io->address,
+                                       fixed_io->address_length,
+                                       ACPI_DECODE_10);
+               break;
+       default:
+               return false;
+       }
+       return true;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_resource_io);
+
+/**
+ * acpi_dev_resource_address_space - Extract ACPI address space information.
+ * @ares: Input ACPI resource object.
+ * @res: Output generic resource object.
+ *
+ * Check if the given ACPI resource object represents an address space resource
+ * and if that's the case, use the information in it to populate the generic
+ * resource object pointed to by @res.
+ */
+bool acpi_dev_resource_address_space(struct acpi_resource *ares,
+                                    struct resource *res)
+{
+       acpi_status status;
+       struct acpi_resource_address64 addr;
+       bool window;
+       u64 len;
+       u8 io_decode;
+
+       switch (ares->type) {
+       case ACPI_RESOURCE_TYPE_ADDRESS16:
+       case ACPI_RESOURCE_TYPE_ADDRESS32:
+       case ACPI_RESOURCE_TYPE_ADDRESS64:
+               break;
+       default:
+               return false;
+       }
+
+       status = acpi_resource_to_address64(ares, &addr);
+       if (ACPI_FAILURE(status))
+               return true;
+
+       res->start = addr.minimum;
+       res->end = addr.maximum;
+       window = addr.producer_consumer == ACPI_PRODUCER;
+
+       switch(addr.resource_type) {
+       case ACPI_MEMORY_RANGE:
+               len = addr.maximum - addr.minimum + 1;
+               res->flags = acpi_dev_memresource_flags(len,
+                                               addr.info.mem.write_protect,
+                                               window);
+               break;
+       case ACPI_IO_RANGE:
+               io_decode = addr.granularity == 0xfff ?
+                               ACPI_DECODE_10 : ACPI_DECODE_16;
+               res->flags = acpi_dev_ioresource_flags(addr.minimum,
+                                                      addr.maximum,
+                                                      io_decode, window);
+               break;
+       case ACPI_BUS_NUMBER_RANGE:
+               res->flags = IORESOURCE_BUS;
+               break;
+       default:
+               res->flags = 0;
+       }
+
+       return true;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_resource_address_space);
+
+/**
+ * acpi_dev_resource_ext_address_space - Extract ACPI address space information.
+ * @ares: Input ACPI resource object.
+ * @res: Output generic resource object.
+ *
+ * Check if the given ACPI resource object represents an extended address space
+ * resource and if that's the case, use the information in it to populate the
+ * generic resource object pointed to by @res.
+ */
+bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
+                                        struct resource *res)
+{
+       struct acpi_resource_extended_address64 *ext_addr;
+       bool window;
+       u64 len;
+       u8 io_decode;
+
+       if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64)
+               return false;
+
+       ext_addr = &ares->data.ext_address64;
+
+       res->start = ext_addr->minimum;
+       res->end = ext_addr->maximum;
+       window = ext_addr->producer_consumer == ACPI_PRODUCER;
+
+       switch(ext_addr->resource_type) {
+       case ACPI_MEMORY_RANGE:
+               len = ext_addr->maximum - ext_addr->minimum + 1;
+               res->flags = acpi_dev_memresource_flags(len,
+                                       ext_addr->info.mem.write_protect,
+                                       window);
+               break;
+       case ACPI_IO_RANGE:
+               io_decode = ext_addr->granularity == 0xfff ?
+                               ACPI_DECODE_10 : ACPI_DECODE_16;
+               res->flags = acpi_dev_ioresource_flags(ext_addr->minimum,
+                                                      ext_addr->maximum,
+                                                      io_decode, window);
+               break;
+       case ACPI_BUS_NUMBER_RANGE:
+               res->flags = IORESOURCE_BUS;
+               break;
+       default:
+               res->flags = 0;
+       }
+
+       return true;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_resource_ext_address_space);
+
+/**
+ * acpi_dev_irq_flags - Determine IRQ resource flags.
+ * @triggering: Triggering type as provided by ACPI.
+ * @polarity: Interrupt polarity as provided by ACPI.
+ * @shareable: Whether or not the interrupt is shareable.
+ */
+unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable)
+{
+       unsigned long flags;
+
+       if (triggering == ACPI_LEVEL_SENSITIVE)
+               flags = polarity == ACPI_ACTIVE_LOW ?
+                       IORESOURCE_IRQ_LOWLEVEL : IORESOURCE_IRQ_HIGHLEVEL;
+       else
+               flags = polarity == ACPI_ACTIVE_LOW ?
+                       IORESOURCE_IRQ_LOWEDGE : IORESOURCE_IRQ_HIGHEDGE;
+
+       if (shareable == ACPI_SHARED)
+               flags |= IORESOURCE_IRQ_SHAREABLE;
+
+       return flags | IORESOURCE_IRQ;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_irq_flags);
+
+static void acpi_dev_irqresource_disabled(struct resource *res, u32 gsi)
+{
+       res->start = gsi;
+       res->end = gsi;
+       res->flags = IORESOURCE_IRQ | IORESOURCE_DISABLED;
+}
+
+static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,
+                                    u8 triggering, u8 polarity, u8 shareable)
+{
+       int irq, p, t;
+
+       if (!valid_IRQ(gsi)) {
+               acpi_dev_irqresource_disabled(res, gsi);
+               return;
+       }
+
+       /*
+        * In IO-APIC mode, use overrided attribute. Two reasons:
+        * 1. BIOS bug in DSDT
+        * 2. BIOS uses IO-APIC mode Interrupt Source Override
+        */
+       if (!acpi_get_override_irq(gsi, &t, &p)) {
+               u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
+               u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
+
+               if (triggering != trig || polarity != pol) {
+                       pr_warning("ACPI: IRQ %d override to %s, %s\n", gsi,
+                                  t ? "edge" : "level", p ? "low" : "high");
+                       triggering = trig;
+                       polarity = pol;
+               }
+       }
+
+       res->flags = acpi_dev_irq_flags(triggering, polarity, shareable);
+       irq = acpi_register_gsi(NULL, gsi, triggering, polarity);
+       if (irq >= 0) {
+               res->start = irq;
+               res->end = irq;
+       } else {
+               acpi_dev_irqresource_disabled(res, gsi);
+       }
+}
+
+/**
+ * acpi_dev_resource_interrupt - Extract ACPI interrupt resource information.
+ * @ares: Input ACPI resource object.
+ * @index: Index into the array of GSIs represented by the resource.
+ * @res: Output generic resource object.
+ *
+ * Check if the given ACPI resource object represents an interrupt resource
+ * and @index does not exceed the resource's interrupt count (true is returned
+ * in that case regardless of the results of the other checks)).  If that's the
+ * case, register the GSI corresponding to @index from the array of interrupts
+ * represented by the resource and populate the generic resource object pointed
+ * to by @res accordingly.  If the registration of the GSI is not successful,
+ * IORESOURCE_DISABLED will be set it that object's flags.
+ */
+bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
+                                struct resource *res)
+{
+       struct acpi_resource_irq *irq;
+       struct acpi_resource_extended_irq *ext_irq;
+
+       switch (ares->type) {
+       case ACPI_RESOURCE_TYPE_IRQ:
+               /*
+                * Per spec, only one interrupt per descriptor is allowed in
+                * _CRS, but some firmware violates this, so parse them all.
+                */
+               irq = &ares->data.irq;
+               if (index >= irq->interrupt_count) {
+                       acpi_dev_irqresource_disabled(res, 0);
+                       return false;
+               }
+               acpi_dev_get_irqresource(res, irq->interrupts[index],
+                                        irq->triggering, irq->polarity,
+                                        irq->sharable);
+               break;
+       case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+               ext_irq = &ares->data.extended_irq;
+               if (index >= ext_irq->interrupt_count) {
+                       acpi_dev_irqresource_disabled(res, 0);
+                       return false;
+               }
+               acpi_dev_get_irqresource(res, ext_irq->interrupts[index],
+                                        ext_irq->triggering, ext_irq->polarity,
+                                        ext_irq->sharable);
+               break;
+       default:
+               return false;
+       }
+
+       return true;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_resource_interrupt);
+
+/**
+ * acpi_dev_free_resource_list - Free resource from %acpi_dev_get_resources().
+ * @list: The head of the resource list to free.
+ */
+void acpi_dev_free_resource_list(struct list_head *list)
+{
+       struct resource_list_entry *rentry, *re;
+
+       list_for_each_entry_safe(rentry, re, list, node) {
+               list_del(&rentry->node);
+               kfree(rentry);
+       }
+}
+EXPORT_SYMBOL_GPL(acpi_dev_free_resource_list);
+
+struct res_proc_context {
+       struct list_head *list;
+       int (*preproc)(struct acpi_resource *, void *);
+       void *preproc_data;
+       int count;
+       int error;
+};
+
+static acpi_status acpi_dev_new_resource_entry(struct resource *r,
+                                              struct res_proc_context *c)
+{
+       struct resource_list_entry *rentry;
+
+       rentry = kmalloc(sizeof(*rentry), GFP_KERNEL);
+       if (!rentry) {
+               c->error = -ENOMEM;
+               return AE_NO_MEMORY;
+       }
+       rentry->res = *r;
+       list_add_tail(&rentry->node, c->list);
+       c->count++;
+       return AE_OK;
+}
+
+static acpi_status acpi_dev_process_resource(struct acpi_resource *ares,
+                                            void *context)
+{
+       struct res_proc_context *c = context;
+       struct resource r;
+       int i;
+
+       if (c->preproc) {
+               int ret;
+
+               ret = c->preproc(ares, c->preproc_data);
+               if (ret < 0) {
+                       c->error = ret;
+                       return AE_CTRL_TERMINATE;
+               } else if (ret > 0) {
+                       return AE_OK;
+               }
+       }
+
+       memset(&r, 0, sizeof(r));
+
+       if (acpi_dev_resource_memory(ares, &r)
+           || acpi_dev_resource_io(ares, &r)
+           || acpi_dev_resource_address_space(ares, &r)
+           || acpi_dev_resource_ext_address_space(ares, &r))
+               return acpi_dev_new_resource_entry(&r, c);
+
+       for (i = 0; acpi_dev_resource_interrupt(ares, i, &r); i++) {
+               acpi_status status;
+
+               status = acpi_dev_new_resource_entry(&r, c);
+               if (ACPI_FAILURE(status))
+                       return status;
+       }
+
+       return AE_OK;
+}
+
+/**
+ * acpi_dev_get_resources - Get current resources of a device.
+ * @adev: ACPI device node to get the resources for.
+ * @list: Head of the resultant list of resources (must be empty).
+ * @preproc: The caller's preprocessing routine.
+ * @preproc_data: Pointer passed to the caller's preprocessing routine.
+ *
+ * Evaluate the _CRS method for the given device node and process its output by
+ * (1) executing the @preproc() rountine provided by the caller, passing the
+ * resource pointer and @preproc_data to it as arguments, for each ACPI resource
+ * returned and (2) converting all of the returned ACPI resources into struct
+ * resource objects if possible.  If the return value of @preproc() in step (1)
+ * is different from 0, step (2) is not applied to the given ACPI resource and
+ * if that value is negative, the whole processing is aborted and that value is
+ * returned as the final error code.
+ *
+ * The resultant struct resource objects are put on the list pointed to by
+ * @list, that must be empty initially, as members of struct resource_list_entry
+ * objects.  Callers of this routine should use %acpi_dev_free_resource_list() to
+ * free that list.
+ *
+ * The number of resources in the output list is returned on success, an error
+ * code reflecting the error condition is returned otherwise.
+ */
+int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,
+                          int (*preproc)(struct acpi_resource *, void *),
+                          void *preproc_data)
+{
+       struct res_proc_context c;
+       acpi_handle not_used;
+       acpi_status status;
+
+       if (!adev || !adev->handle || !list_empty(list))
+               return -EINVAL;
+
+       status = acpi_get_handle(adev->handle, METHOD_NAME__CRS, &not_used);
+       if (ACPI_FAILURE(status))
+               return 0;
+
+       c.list = list;
+       c.preproc = preproc;
+       c.preproc_data = preproc_data;
+       c.count = 0;
+       c.error = 0;
+       status = acpi_walk_resources(adev->handle, METHOD_NAME__CRS,
+                                    acpi_dev_process_resource, &c);
+       if (ACPI_FAILURE(status)) {
+               acpi_dev_free_resource_list(list);
+               return c.error ? c.error : -EIO;
+       }
+
+       return c.count;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_get_resources);
index 1fcb867..53502d1 100644 (file)
@@ -29,6 +29,27 @@ extern struct acpi_device *acpi_root;
 
 static const char *dummy_hid = "device";
 
+/*
+ * The following ACPI IDs are known to be suitable for representing as
+ * platform devices.
+ */
+static const struct acpi_device_id acpi_platform_device_ids[] = {
+
+       { "PNP0D40" },
+
+       /* Haswell LPSS devices */
+       { "INT33C0", 0 },
+       { "INT33C1", 0 },
+       { "INT33C2", 0 },
+       { "INT33C3", 0 },
+       { "INT33C4", 0 },
+       { "INT33C5", 0 },
+       { "INT33C6", 0 },
+       { "INT33C7", 0 },
+
+       { }
+};
+
 static LIST_HEAD(acpi_device_list);
 static LIST_HEAD(acpi_bus_id_list);
 DEFINE_MUTEX(acpi_device_lock);
@@ -97,6 +118,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 +139,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;
@@ -157,6 +182,7 @@ err_out:
        kfree(context);
        return;
 }
+EXPORT_SYMBOL(acpi_bus_hot_remove_device);
 
 static ssize_t
 acpi_eject_store(struct device *d, struct device_attribute *attr,
@@ -216,6 +242,25 @@ acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *bu
 }
 static DEVICE_ATTR(hid, 0444, acpi_device_hid_show, NULL);
 
+static ssize_t acpi_device_uid_show(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+{
+       struct acpi_device *acpi_dev = to_acpi_device(dev);
+
+       return sprintf(buf, "%s\n", acpi_dev->pnp.unique_id);
+}
+static DEVICE_ATTR(uid, 0444, acpi_device_uid_show, NULL);
+
+static ssize_t acpi_device_adr_show(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+{
+       struct acpi_device *acpi_dev = to_acpi_device(dev);
+
+       return sprintf(buf, "0x%08x\n",
+                      (unsigned int)(acpi_dev->pnp.bus_address));
+}
+static DEVICE_ATTR(adr, 0444, acpi_device_adr_show, NULL);
+
 static ssize_t
 acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *buf) {
        struct acpi_device *acpi_dev = to_acpi_device(dev);
@@ -259,11 +304,21 @@ static ssize_t description_show(struct device *dev,
 }
 static DEVICE_ATTR(description, 0444, description_show, NULL);
 
+static ssize_t
+acpi_device_sun_show(struct device *dev, struct device_attribute *attr,
+                    char *buf) {
+       struct acpi_device *acpi_dev = to_acpi_device(dev);
+
+       return sprintf(buf, "%lu\n", acpi_dev->pnp.sun);
+}
+static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL);
+
 static int acpi_device_setup_files(struct acpi_device *dev)
 {
        struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
        acpi_status status;
        acpi_handle temp;
+       unsigned long long sun;
        int result = 0;
 
        /*
@@ -300,6 +355,21 @@ static int acpi_device_setup_files(struct acpi_device *dev)
                        goto end;
        }
 
+       if (dev->flags.bus_address)
+               result = device_create_file(&dev->dev, &dev_attr_adr);
+       if (dev->pnp.unique_id)
+               result = device_create_file(&dev->dev, &dev_attr_uid);
+
+       status = acpi_evaluate_integer(dev->handle, "_SUN", NULL, &sun);
+       if (ACPI_SUCCESS(status)) {
+               dev->pnp.sun = (unsigned long)sun;
+               result = device_create_file(&dev->dev, &dev_attr_sun);
+               if (result)
+                       goto end;
+       } else {
+               dev->pnp.sun = (unsigned long)-1;
+       }
+
         /*
          * If device has _EJ0, 'eject' file is created that is used to trigger
          * hot-removal function from userland.
@@ -331,6 +401,14 @@ static void acpi_device_remove_files(struct acpi_device *dev)
        if (ACPI_SUCCESS(status))
                device_remove_file(&dev->dev, &dev_attr_eject);
 
+       status = acpi_get_handle(dev->handle, "_SUN", &temp);
+       if (ACPI_SUCCESS(status))
+               device_remove_file(&dev->dev, &dev_attr_sun);
+
+       if (dev->pnp.unique_id)
+               device_remove_file(&dev->dev, &dev_attr_uid);
+       if (dev->flags.bus_address)
+               device_remove_file(&dev->dev, &dev_attr_adr);
        device_remove_file(&dev->dev, &dev_attr_modalias);
        device_remove_file(&dev->dev, &dev_attr_hid);
        if (dev->handle)
@@ -340,8 +418,8 @@ static void acpi_device_remove_files(struct acpi_device *dev)
                        ACPI Bus operations
    -------------------------------------------------------------------------- */
 
-int acpi_match_device_ids(struct acpi_device *device,
-                         const struct acpi_device_id *ids)
+static const struct acpi_device_id *__acpi_match_device(
+       struct acpi_device *device, const struct acpi_device_id *ids)
 {
        const struct acpi_device_id *id;
        struct acpi_hardware_id *hwid;
@@ -351,14 +429,44 @@ int acpi_match_device_ids(struct acpi_device *device,
         * driver for it.
         */
        if (!device->status.present)
-               return -ENODEV;
+               return NULL;
 
        for (id = ids; id->id[0]; id++)
                list_for_each_entry(hwid, &device->pnp.ids, list)
                        if (!strcmp((char *) id->id, hwid->id))
-                               return 0;
+                               return id;
 
-       return -ENOENT;
+       return NULL;
+}
+
+/**
+ * acpi_match_device - Match a struct device against a given list of ACPI IDs
+ * @ids: Array of struct acpi_device_id object to match against.
+ * @dev: The device structure to match.
+ *
+ * Check if @dev has a valid ACPI handle and if there is a struct acpi_device
+ * object for that handle and use that object to match against a given list of
+ * device IDs.
+ *
+ * Return a pointer to the first matching ID on success or %NULL on failure.
+ */
+const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
+                                              const struct device *dev)
+{
+       struct acpi_device *adev;
+
+       if (!ids || !ACPI_HANDLE(dev)
+           || ACPI_FAILURE(acpi_bus_get_device(ACPI_HANDLE(dev), &adev)))
+               return NULL;
+
+       return __acpi_match_device(adev, ids);
+}
+EXPORT_SYMBOL_GPL(acpi_match_device);
+
+int acpi_match_device_ids(struct acpi_device *device,
+                         const struct acpi_device_id *ids)
+{
+       return __acpi_match_device(device, ids) ? 0 : -ENOENT;
 }
 EXPORT_SYMBOL(acpi_match_device_ids);
 
@@ -377,6 +485,7 @@ static void acpi_device_release(struct device *dev)
        struct acpi_device *acpi_dev = to_acpi_device(dev);
 
        acpi_free_ids(acpi_dev);
+       kfree(acpi_dev->pnp.unique_id);
        kfree(acpi_dev);
 }
 
@@ -859,8 +968,8 @@ acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
 static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
 {
        struct acpi_device_id button_device_ids[] = {
-               {"PNP0C0D", 0},
                {"PNP0C0C", 0},
+               {"PNP0C0D", 0},
                {"PNP0C0E", 0},
                {"", 0},
        };
@@ -872,6 +981,11 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
        /* Power button, Lid switch always enable wakeup */
        if (!acpi_match_device_ids(device, button_device_ids)) {
                device->wakeup.flags.run_wake = 1;
+               if (!acpi_match_device_ids(device, &button_device_ids[1])) {
+                       /* Do not use Lid/sleep button for S5 wakeup */
+                       if (device->wakeup.sleep_state == ACPI_STATE_S5)
+                               device->wakeup.sleep_state = ACPI_STATE_S4;
+               }
                device_set_wakeup_capable(&device->dev, true);
                return;
        }
@@ -965,8 +1079,10 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
                 * D3hot is only valid if _PR3 present.
                 */
                if (ps->resources.count ||
-                   (ps->flags.explicit_set && i < ACPI_STATE_D3_HOT))
+                   (ps->flags.explicit_set && i < ACPI_STATE_D3_HOT)) {
                        ps->flags.valid = 1;
+                       ps->flags.os_accessible = 1;
+               }
 
                ps->power = -1; /* Unknown - driver assigned */
                ps->latency = -1;       /* Unknown - driver assigned */
@@ -982,6 +1098,11 @@ static int acpi_bus_get_power_flags(struct acpi_device *device)
        if (device->power.states[ACPI_STATE_D3_HOT].flags.explicit_set)
                device->power.states[ACPI_STATE_D3_COLD].flags.explicit_set = 1;
 
+       /* Presence of _PS3 or _PRx means we can put the device into D3 cold */
+       if (device->power.states[ACPI_STATE_D3_HOT].flags.explicit_set ||
+                       device->power.flags.power_resources)
+               device->power.states[ACPI_STATE_D3_COLD].flags.os_accessible = 1;
+
        acpi_bus_init_power(device);
 
        return 0;
@@ -1013,11 +1134,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;
@@ -1185,7 +1301,7 @@ static void acpi_device_set_id(struct acpi_device *device)
 {
        acpi_status status;
        struct acpi_device_info *info;
-       struct acpica_device_id_list *cid_list;
+       struct acpi_pnp_device_id_list *cid_list;
        int i;
 
        switch (device->device_type) {
@@ -1212,6 +1328,9 @@ static void acpi_device_set_id(struct acpi_device *device)
                        device->pnp.bus_address = info->address;
                        device->flags.bus_address = 1;
                }
+               if (info->valid & ACPI_VALID_UID)
+                       device->pnp.unique_id = kstrdup(info->unique_id.string,
+                                                       GFP_KERNEL);
 
                kfree(info);
 
@@ -1483,8 +1602,13 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,
         */
        device = NULL;
        acpi_bus_get_device(handle, &device);
-       if (ops->acpi_op_add && !device)
+       if (ops->acpi_op_add && !device) {
                acpi_add_single_object(&device, handle, type, sta, ops);
+               /* Is the device a known good platform device? */
+               if (device
+                   && !acpi_match_device_ids(device, acpi_platform_device_ids))
+                       acpi_create_platform_device(device);
+       }
 
        if (!device)
                return AE_CTRL_DEPTH;
index fdcdbb6..2fcc67d 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/reboot.h>
 #include <linux/acpi.h>
 #include <linux/module.h>
-#include <linux/pm_runtime.h>
 
 #include <asm/io.h>
 
@@ -81,6 +80,12 @@ static int acpi_sleep_prepare(u32 acpi_state)
 
 #ifdef CONFIG_ACPI_SLEEP
 static u32 acpi_target_sleep_state = ACPI_STATE_S0;
+
+u32 acpi_target_system_state(void)
+{
+       return acpi_target_sleep_state;
+}
+
 static bool pwr_btn_event_pending;
 
 /*
@@ -98,6 +103,21 @@ void __init acpi_nvs_nosave(void)
 }
 
 /*
+ * 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'
  * kernel command line option that causes the following variable to be set.
@@ -109,6 +129,180 @@ void __init acpi_old_suspend_ordering(void)
        old_suspend_ordering = true;
 }
 
+static int __init init_old_suspend_ordering(const struct dmi_system_id *d)
+{
+       acpi_old_suspend_ordering();
+       return 0;
+}
+
+static int __init init_nvs_nosave(const struct dmi_system_id *d)
+{
+       acpi_nvs_nosave();
+       return 0;
+}
+
+static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
+       {
+       .callback = init_old_suspend_ordering,
+       .ident = "Abit KN9 (nForce4 variant)",
+       .matches = {
+               DMI_MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"),
+               DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"),
+               },
+       },
+       {
+       .callback = init_old_suspend_ordering,
+       .ident = "HP xw4600 Workstation",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"),
+               },
+       },
+       {
+       .callback = init_old_suspend_ordering,
+       .ident = "Asus Pundit P1-AH2 (M2N8L motherboard)",
+       .matches = {
+               DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek Computer INC."),
+               DMI_MATCH(DMI_BOARD_NAME, "M2N8L"),
+               },
+       },
+       {
+       .callback = init_old_suspend_ordering,
+       .ident = "Panasonic CF51-2L",
+       .matches = {
+               DMI_MATCH(DMI_BOARD_VENDOR,
+                               "Matsushita Electric Industrial Co.,Ltd."),
+               DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"),
+               },
+       },
+       {
+       .callback = init_nvs_nosave,
+       .ident = "Sony Vaio VGN-FW21E",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21E"),
+               },
+       },
+       {
+       .callback = init_nvs_nosave,
+       .ident = "Sony Vaio VPCEB17FX",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB17FX"),
+               },
+       },
+       {
+       .callback = init_nvs_nosave,
+       .ident = "Sony Vaio VGN-SR11M",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR11M"),
+               },
+       },
+       {
+       .callback = init_nvs_nosave,
+       .ident = "Everex StepNote Series",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Everex Systems, Inc."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "Everex StepNote Series"),
+               },
+       },
+       {
+       .callback = init_nvs_nosave,
+       .ident = "Sony Vaio VPCEB1Z1E",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1Z1E"),
+               },
+       },
+       {
+       .callback = init_nvs_nosave,
+       .ident = "Sony Vaio VGN-NW130D",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NW130D"),
+               },
+       },
+       {
+       .callback = init_nvs_nosave,
+       .ident = "Sony Vaio VPCCW29FX",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "VPCCW29FX"),
+               },
+       },
+       {
+       .callback = init_nvs_nosave,
+       .ident = "Averatec AV1020-ED2",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "AVERATEC"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "1000 Series"),
+               },
+       },
+       {
+       .callback = init_old_suspend_ordering,
+       .ident = "Asus A8N-SLI DELUXE",
+       .matches = {
+               DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+               DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI DELUXE"),
+               },
+       },
+       {
+       .callback = init_old_suspend_ordering,
+       .ident = "Asus A8N-SLI Premium",
+       .matches = {
+               DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+               DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI Premium"),
+               },
+       },
+       {
+       .callback = init_nvs_nosave,
+       .ident = "Sony Vaio VGN-SR26GN_P",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR26GN_P"),
+               },
+       },
+       {
+       .callback = init_nvs_nosave,
+       .ident = "Sony Vaio VPCEB1S1E",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1S1E"),
+               },
+       },
+       {
+       .callback = init_nvs_nosave,
+       .ident = "Sony Vaio VGN-FW520F",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW520F"),
+               },
+       },
+       {
+       .callback = init_nvs_nosave,
+       .ident = "Asus K54C",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "K54C"),
+               },
+       },
+       {
+       .callback = init_nvs_nosave,
+       .ident = "Asus K54HR",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "K54HR"),
+               },
+       },
+       {},
+};
+
+static void acpi_sleep_dmi_check(void)
+{
+       dmi_check_system(acpisleep_dmi_table);
+}
+
 /**
  * acpi_pm_freeze - Disable the GPEs and suspend EC transactions.
  */
@@ -224,6 +418,7 @@ static void acpi_pm_end(void)
 }
 #else /* !CONFIG_ACPI_SLEEP */
 #define acpi_target_sleep_state        ACPI_STATE_S0
+static inline void acpi_sleep_dmi_check(void) {}
 #endif /* CONFIG_ACPI_SLEEP */
 
 #ifdef CONFIG_SUSPEND
@@ -243,7 +438,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;
 
@@ -382,167 +577,6 @@ static const struct platform_suspend_ops acpi_suspend_ops_old = {
        .end = acpi_pm_end,
        .recover = acpi_pm_finish,
 };
-
-static int __init init_old_suspend_ordering(const struct dmi_system_id *d)
-{
-       old_suspend_ordering = true;
-       return 0;
-}
-
-static int __init init_nvs_nosave(const struct dmi_system_id *d)
-{
-       acpi_nvs_nosave();
-       return 0;
-}
-
-static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
-       {
-       .callback = init_old_suspend_ordering,
-       .ident = "Abit KN9 (nForce4 variant)",
-       .matches = {
-               DMI_MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"),
-               DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"),
-               },
-       },
-       {
-       .callback = init_old_suspend_ordering,
-       .ident = "HP xw4600 Workstation",
-       .matches = {
-               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-               DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"),
-               },
-       },
-       {
-       .callback = init_old_suspend_ordering,
-       .ident = "Asus Pundit P1-AH2 (M2N8L motherboard)",
-       .matches = {
-               DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek Computer INC."),
-               DMI_MATCH(DMI_BOARD_NAME, "M2N8L"),
-               },
-       },
-       {
-       .callback = init_old_suspend_ordering,
-       .ident = "Panasonic CF51-2L",
-       .matches = {
-               DMI_MATCH(DMI_BOARD_VENDOR,
-                               "Matsushita Electric Industrial Co.,Ltd."),
-               DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"),
-               },
-       },
-       {
-       .callback = init_nvs_nosave,
-       .ident = "Sony Vaio VGN-FW21E",
-       .matches = {
-               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
-               DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21E"),
-               },
-       },
-       {
-       .callback = init_nvs_nosave,
-       .ident = "Sony Vaio VPCEB17FX",
-       .matches = {
-               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
-               DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB17FX"),
-               },
-       },
-       {
-       .callback = init_nvs_nosave,
-       .ident = "Sony Vaio VGN-SR11M",
-       .matches = {
-               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
-               DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR11M"),
-               },
-       },
-       {
-       .callback = init_nvs_nosave,
-       .ident = "Everex StepNote Series",
-       .matches = {
-               DMI_MATCH(DMI_SYS_VENDOR, "Everex Systems, Inc."),
-               DMI_MATCH(DMI_PRODUCT_NAME, "Everex StepNote Series"),
-               },
-       },
-       {
-       .callback = init_nvs_nosave,
-       .ident = "Sony Vaio VPCEB1Z1E",
-       .matches = {
-               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
-               DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1Z1E"),
-               },
-       },
-       {
-       .callback = init_nvs_nosave,
-       .ident = "Sony Vaio VGN-NW130D",
-       .matches = {
-               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
-               DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NW130D"),
-               },
-       },
-       {
-       .callback = init_nvs_nosave,
-       .ident = "Sony Vaio VPCCW29FX",
-       .matches = {
-               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
-               DMI_MATCH(DMI_PRODUCT_NAME, "VPCCW29FX"),
-               },
-       },
-       {
-       .callback = init_nvs_nosave,
-       .ident = "Averatec AV1020-ED2",
-       .matches = {
-               DMI_MATCH(DMI_SYS_VENDOR, "AVERATEC"),
-               DMI_MATCH(DMI_PRODUCT_NAME, "1000 Series"),
-               },
-       },
-       {
-       .callback = init_old_suspend_ordering,
-       .ident = "Asus A8N-SLI DELUXE",
-       .matches = {
-               DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
-               DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI DELUXE"),
-               },
-       },
-       {
-       .callback = init_old_suspend_ordering,
-       .ident = "Asus A8N-SLI Premium",
-       .matches = {
-               DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
-               DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI Premium"),
-               },
-       },
-       {
-       .callback = init_nvs_nosave,
-       .ident = "Sony Vaio VGN-SR26GN_P",
-       .matches = {
-               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
-               DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR26GN_P"),
-               },
-       },
-       {
-       .callback = init_nvs_nosave,
-       .ident = "Sony Vaio VGN-FW520F",
-       .matches = {
-               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
-               DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW520F"),
-               },
-       },
-       {
-       .callback = init_nvs_nosave,
-       .ident = "Asus K54C",
-       .matches = {
-               DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
-               DMI_MATCH(DMI_PRODUCT_NAME, "K54C"),
-               },
-       },
-       {
-       .callback = init_nvs_nosave,
-       .ident = "Asus K54HR",
-       .matches = {
-               DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
-               DMI_MATCH(DMI_PRODUCT_NAME, "K54HR"),
-               },
-       },
-       {},
-};
 #endif /* CONFIG_SUSPEND */
 
 #ifdef CONFIG_HIBERNATION
@@ -681,177 +715,6 @@ int acpi_suspend(u32 acpi_state)
        return -EINVAL;
 }
 
-#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
- *
- *     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.
- *
- *     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.
- */
-
-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;
-
-       if (d_max_in < ACPI_STATE_D0 || d_max_in > ACPI_STATE_D3)
-               return -EINVAL;
-       if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
-               printk(KERN_DEBUG "ACPI handle has no context!\n");
-               return -ENODEV;
-       }
-
-       acpi_method[2] = '0' + acpi_target_sleep_state;
-       /*
-        * If the sleep state is S0, the lowest limit from ACPI is D3,
-        * but if the device has _S0W, we will use the value from _S0W
-        * as the lowest limit from ACPI.  Finally, we will constrain
-        * the lowest limit with the specified one.
-        */
-       d_min = ACPI_STATE_D0;
-       d_max = ACPI_STATE_D3;
-
-       /*
-        * If present, _SxD methods return the minimum D-state (highest power
-        * state) we can use for the corresponding S-states.  Otherwise, the
-        * minimum D-state is D0 (ACPI 3.x).
-        *
-        * 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)
-               acpi_evaluate_integer(handle, acpi_method, NULL, &d_min);
-
-       /*
-        * If _PRW says we can wake up the system from the target sleep state,
-        * the D-state returned by _SxD is sufficient for that (we assume a
-        * wakeup-aware driver if wake is set).  Still, if _SxW exists
-        * (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)) {
-               acpi_status status;
-
-               acpi_method[3] = 'W';
-               status = acpi_evaluate_integer(handle, acpi_method, NULL,
-                                               &d_max);
-               if (ACPI_FAILURE(status)) {
-                       if (acpi_target_sleep_state != ACPI_STATE_S0 ||
-                           status != AE_NOT_FOUND)
-                               d_max = d_min;
-               } else if (d_max < d_min) {
-                       /* Warn the user of the broken DSDT */
-                       printk(KERN_WARNING "ACPI: Wrong value from %s\n",
-                               acpi_method);
-                       /* Sanitize it */
-                       d_min = d_max;
-               }
-       }
-
-       if (d_max_in < d_min)
-               return -EINVAL;
-       if (d_min_p)
-               *d_min_p = d_min;
-       /* constrain d_max with specified lowest limit (max number) */
-       if (d_max > d_max_in) {
-               for (d_max = d_max_in; d_max > d_min; d_max--) {
-                       if (adev->power.states[d_max].flags.valid)
-                               break;
-               }
-       }
-       return d_max;
-}
-EXPORT_SYMBOL(acpi_pm_device_sleep_state);
-#endif /* CONFIG_PM */
-
-#ifdef CONFIG_PM_SLEEP
-/**
- * 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.
- *
- * Find the ACPI device object corresponding to @pci_dev and try to
- * enable/disable the GPE associated with it.
- */
-int acpi_pm_device_run_wake(struct device *phys_dev, bool enable)
-{
-       struct acpi_device *dev;
-       acpi_handle handle;
-
-       if (!device_run_wake(phys_dev))
-               return -EINVAL;
-
-       handle = DEVICE_ACPI_HANDLE(phys_dev);
-       if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &dev))) {
-               dev_dbg(phys_dev, "ACPI handle has no context in %s!\n",
-                       __func__);
-               return -ENODEV;
-       }
-
-       if (enable) {
-               acpi_enable_wakeup_device_power(dev, ACPI_STATE_S0);
-               acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number);
-       } else {
-               acpi_disable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number);
-               acpi_disable_wakeup_device_power(dev);
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL(acpi_pm_device_run_wake);
-
-/**
- *     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
- */
-int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
-{
-       acpi_handle handle;
-       struct acpi_device *adev;
-       int error;
-
-       if (!device_can_wakeup(dev))
-               return -EINVAL;
-
-       handle = DEVICE_ACPI_HANDLE(dev);
-       if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
-               dev_dbg(dev, "ACPI handle has no context in %s!\n", __func__);
-               return -ENODEV;
-       }
-
-       error = enable ?
-               acpi_enable_wakeup_device_power(adev, acpi_target_sleep_state) :
-               acpi_disable_wakeup_device_power(adev);
-       if (!error)
-               dev_info(dev, "wake-up capability %s by ACPI\n",
-                               enable ? "enabled" : "disabled");
-
-       return error;
-}
-#endif  /* CONFIG_PM_SLEEP */
-
 static void acpi_power_off_prepare(void)
 {
        /* Prepare to power off the system */
@@ -873,13 +736,13 @@ int __init acpi_sleep_init(void)
        u8 type_a, type_b;
 #ifdef CONFIG_SUSPEND
        int i = 0;
-
-       dmi_check_system(acpisleep_dmi_table);
 #endif
 
        if (acpi_disabled)
                return 0;
 
+       acpi_sleep_dmi_check();
+
        sleep_states[ACPI_STATE_S0] = 1;
        printk(KERN_INFO PREFIX "(supports S0");
 
index 7c3f98b..ea61ca9 100644 (file)
@@ -476,7 +476,7 @@ static void fixed_event_count(u32 event_number)
        return;
 }
 
-static void acpi_gbl_event_handler(u32 event_type, acpi_handle device,
+static void acpi_global_event_handler(u32 event_type, acpi_handle device,
        u32 event_number, void *context)
 {
        if (event_type == ACPI_EVENT_TYPE_GPE)
@@ -638,7 +638,7 @@ void acpi_irq_stats_init(void)
        if (all_counters == NULL)
                goto fail;
 
-       status = acpi_install_global_event_handler(acpi_gbl_event_handler, NULL);
+       status = acpi_install_global_event_handler(acpi_global_event_handler, NULL);
        if (ACPI_FAILURE(status))
                goto fail;
 
index 804204d..6e8cc16 100644 (file)
@@ -984,6 +984,38 @@ static void acpi_thermal_notify(struct acpi_device *device, u32 event)
        }
 }
 
+/*
+ * On some platforms, the AML code has dependency about
+ * the evaluating order of _TMP and _CRT/_HOT/_PSV/_ACx.
+ * 1. On HP Pavilion G4-1016tx, _TMP must be invoked after
+ *    /_CRT/_HOT/_PSV/_ACx, or else system will be power off.
+ * 2. On HP Compaq 6715b/6715s, the return value of _PSV is 0
+ *    if _TMP has never been evaluated.
+ *
+ * As this dependency is totally transparent to OS, evaluate
+ * all of them once, in the order of _CRT/_HOT/_PSV/_ACx,
+ * _TMP, before they are actually used.
+ */
+static void acpi_thermal_aml_dependency_fix(struct acpi_thermal *tz)
+{
+       acpi_handle handle = tz->device->handle;
+       unsigned long long value;
+       int i;
+
+       acpi_evaluate_integer(handle, "_CRT", NULL, &value);
+       acpi_evaluate_integer(handle, "_HOT", NULL, &value);
+       acpi_evaluate_integer(handle, "_PSV", NULL, &value);
+       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
+               char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
+               acpi_status status;
+
+               status = acpi_evaluate_integer(handle, name, NULL, &value);
+               if (status == AE_NOT_FOUND)
+                       break;
+       }
+       acpi_evaluate_integer(handle, "_TMP", NULL, &value);
+}
+
 static int acpi_thermal_get_info(struct acpi_thermal *tz)
 {
        int result = 0;
@@ -992,6 +1024,8 @@ static int acpi_thermal_get_info(struct acpi_thermal *tz)
        if (!tz)
                return -EINVAL;
 
+       acpi_thermal_aml_dependency_fix(tz);
+
        /* Get trip points [_CRT, _PSV, etc.] (required) */
        result = acpi_thermal_get_trip_points(tz);
        if (result)
index 462f7e3..7443713 100644 (file)
@@ -28,6 +28,8 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/types.h>
+#include <linux/hardirq.h>
+#include <linux/acpi.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
@@ -457,3 +459,39 @@ acpi_evaluate_hotplug_ost(acpi_handle handle, u32 source_event,
 #endif
 }
 EXPORT_SYMBOL(acpi_evaluate_hotplug_ost);
+
+/**
+ * acpi_handle_printk: Print message with ACPI prefix and object path
+ *
+ * This function is called through acpi_handle_<level> macros and prints
+ * a message with ACPI prefix and object path.  This function acquires
+ * the global namespace mutex to obtain an object path.  In interrupt
+ * context, it shows the object path as <n/a>.
+ */
+void
+acpi_handle_printk(const char *level, acpi_handle handle, const char *fmt, ...)
+{
+       struct va_format vaf;
+       va_list args;
+       struct acpi_buffer buffer = {
+               .length = ACPI_ALLOCATE_BUFFER,
+               .pointer = NULL
+       };
+       const char *path;
+
+       va_start(args, fmt);
+       vaf.fmt = fmt;
+       vaf.va = &args;
+
+       if (in_interrupt() ||
+           acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer) != AE_OK)
+               path = "<n/a>";
+       else
+               path = buffer.pointer;
+
+       printk("%sACPI: %s: %pV", level, path, &vaf);
+
+       va_end(args);
+       kfree(buffer.pointer);
+}
+EXPORT_SYMBOL(acpi_handle_printk);
index f94d4c8..ac9a69c 100644 (file)
@@ -389,6 +389,12 @@ static int __init video_set_bqc_offset(const struct dmi_system_id *d)
        return 0;
 }
 
+static int video_ignore_initial_backlight(const struct dmi_system_id *d)
+{
+       use_bios_initial_backlight = 0;
+       return 0;
+}
+
 static struct dmi_system_id video_dmi_table[] __initdata = {
        /*
         * Broken _BQC workaround http://bugzilla.kernel.org/show_bug.cgi?id=13121
@@ -433,6 +439,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
                DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720"),
                },
        },
+       {
+        .callback = video_ignore_initial_backlight,
+        .ident = "HP Folio 13-2000",
+        .matches = {
+               DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13 - 2000 Notebook PC"),
+               },
+       },
        {}
 };
 
@@ -1345,12 +1359,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 b728880..4ac2593 100644 (file)
@@ -156,6 +156,14 @@ static struct dmi_system_id video_detect_dmi_table[] = {
                DMI_MATCH(DMI_BOARD_NAME, "X360"),
                },
        },
+       {
+       .callback = video_detect_force_vendor,
+       .ident = "Asus UL30VT",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "UL30VT"),
+               },
+       },
        { },
 };
 
index b1ae480..b7078af 100644 (file)
@@ -238,7 +238,7 @@ static int __devexit ahci_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int ahci_suspend(struct device *dev)
 {
        struct ahci_platform_data *pdata = dev_get_platdata(dev);
index fd9ecf7..5b0ba3f 100644 (file)
@@ -1105,10 +1105,15 @@ static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev,
        struct acpi_device *acpi_dev;
        struct acpi_device_power_state *states;
 
-       if (ap->flags & ATA_FLAG_ACPI_SATA)
-               ata_dev = &ap->link.device[sdev->channel];
-       else
+       if (ap->flags & ATA_FLAG_ACPI_SATA) {
+               if (!sata_pmp_attached(ap))
+                       ata_dev = &ap->link.device[sdev->id];
+               else
+                       ata_dev = &ap->pmp_link[sdev->channel].device[sdev->id];
+       }
+       else {
                ata_dev = &ap->link.device[sdev->id];
+       }
 
        *handle = ata_dev_acpi_handle(ata_dev);
 
index 3cc7096..f46fbd3 100644 (file)
@@ -2942,6 +2942,10 @@ const struct ata_timing *ata_timing_find_mode(u8 xfer_mode)
 
        if (xfer_mode == t->mode)
                return t;
+
+       WARN_ONCE(true, "%s: unable to find timing for xfer_mode 0x%x\n",
+                       __func__, xfer_mode);
+
        return NULL;
 }
 
index e3bda07..a6df6a3 100644 (file)
@@ -1052,6 +1052,8 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev)
 {
        sdev->use_10_for_rw = 1;
        sdev->use_10_for_ms = 1;
+       sdev->no_report_opcodes = 1;
+       sdev->no_write_same = 1;
 
        /* Schedule policy is determined by ->qc_defer() callback and
         * it needs to see every deferred qc.  Set dev_blocked to 1 to
index 26201eb..371fd2c 100644 (file)
@@ -317,6 +317,12 @@ static int cf_init(struct arasan_cf_dev *acdev)
                return ret;
        }
 
+       ret = clk_set_rate(acdev->clk, 166000000);
+       if (ret) {
+               dev_warn(acdev->host->dev, "clock set rate failed");
+               return ret;
+       }
+
        spin_lock_irqsave(&acdev->host->lock, flags);
        /* configure CF interface clock */
        writel((pdata->cf_if_clk <= CF_IF_CLK_200M) ? pdata->cf_if_clk :
@@ -908,7 +914,7 @@ static int __devexit arasan_cf_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int arasan_cf_suspend(struct device *dev)
 {
        struct ata_host *host = dev_get_drvdata(dev);
index 0d7c4c2..400bf1c 100644 (file)
@@ -260,7 +260,7 @@ static const struct of_device_id ahci_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, ahci_of_match);
 
-static int __init ahci_highbank_probe(struct platform_device *pdev)
+static int __devinit ahci_highbank_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct ahci_host_priv *hpriv;
@@ -378,7 +378,7 @@ static int __devexit ahci_highbank_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int ahci_highbank_suspend(struct device *dev)
 {
        struct ata_host *host = dev_get_drvdata(dev);
index 44a4256..08608de 100644 (file)
@@ -142,6 +142,39 @@ static int k2_sata_scr_write(struct ata_link *link,
        return 0;
 }
 
+static int k2_sata_softreset(struct ata_link *link,
+                            unsigned int *class, unsigned long deadline)
+{
+       u8 dmactl;
+       void __iomem *mmio = link->ap->ioaddr.bmdma_addr;
+
+       dmactl = readb(mmio + ATA_DMA_CMD);
+
+       /* Clear the start bit */
+       if (dmactl & ATA_DMA_START) {
+               dmactl &= ~ATA_DMA_START;
+               writeb(dmactl, mmio + ATA_DMA_CMD);
+       }
+
+       return ata_sff_softreset(link, class, deadline);
+}
+
+static int k2_sata_hardreset(struct ata_link *link,
+                            unsigned int *class, unsigned long deadline)
+{
+       u8 dmactl;
+       void __iomem *mmio = link->ap->ioaddr.bmdma_addr;
+
+       dmactl = readb(mmio + ATA_DMA_CMD);
+
+       /* Clear the start bit */
+       if (dmactl & ATA_DMA_START) {
+               dmactl &= ~ATA_DMA_START;
+               writeb(dmactl, mmio + ATA_DMA_CMD);
+       }
+
+       return sata_sff_hardreset(link, class, deadline);
+}
 
 static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
 {
@@ -346,6 +379,8 @@ static struct scsi_host_template k2_sata_sht = {
 
 static struct ata_port_operations k2_sata_ops = {
        .inherits               = &ata_bmdma_port_ops,
+       .softreset              = k2_sata_softreset,
+       .hardreset              = k2_sata_hardreset,
        .sff_tf_load            = k2_sata_tf_load,
        .sff_tf_read            = k2_sata_tf_read,
        .sff_check_status       = k2_stat_check_status,
index 89b30f3..ff7bb8a 100644 (file)
@@ -1961,6 +1961,7 @@ static int __devinit ucode_init (loader_block * lb, amb_dev * dev) {
     res = loader_verify(lb, dev, rec);
     if (res)
       break;
+    rec = ihex_next_binrec(rec);
   }
   release_firmware(fw);
   if (!res)
index 08b4c52..b34b5cd 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 abea76c..150a415 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 560a717..bc256b6 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 9a14694..0ca5442 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;
@@ -60,8 +57,8 @@ struct cma *dma_contiguous_default_area;
  * Users, who want to set the size of global CMA area for their system
  * should use cma= kernel parameter.
  */
-static const unsigned long size_bytes = CMA_SIZE_MBYTES * SZ_1M;
-static long size_cmdline = -1;
+static const phys_addr_t size_bytes = CMA_SIZE_MBYTES * SZ_1M;
+static phys_addr_t size_cmdline = -1;
 
 static int __init early_cma(char *p)
 {
@@ -73,7 +70,7 @@ early_param("cma", early_cma);
 
 #ifdef CONFIG_CMA_SIZE_PERCENTAGE
 
-static unsigned long __init __maybe_unused cma_early_percent_memory(void)
+static phys_addr_t __init __maybe_unused cma_early_percent_memory(void)
 {
        struct memblock_region *reg;
        unsigned long total_pages = 0;
@@ -91,7 +88,7 @@ static unsigned long __init __maybe_unused cma_early_percent_memory(void)
 
 #else
 
-static inline __maybe_unused unsigned long cma_early_percent_memory(void)
+static inline __maybe_unused phys_addr_t cma_early_percent_memory(void)
 {
        return 0;
 }
@@ -109,7 +106,7 @@ static inline __maybe_unused unsigned long cma_early_percent_memory(void)
  */
 void __init dma_contiguous_reserve(phys_addr_t limit)
 {
-       unsigned long selected_size = 0;
+       phys_addr_t selected_size = 0;
 
        pr_debug("%s(limit %08lx)\n", __func__, (unsigned long)limit);
 
@@ -129,7 +126,7 @@ void __init dma_contiguous_reserve(phys_addr_t limit)
 
        if (selected_size) {
                pr_debug("%s: reserving %ld MiB for global area\n", __func__,
-                        selected_size / SZ_1M);
+                        (unsigned long)selected_size / SZ_1M);
 
                dma_declare_contiguous(NULL, selected_size, 0, limit);
        }
@@ -230,11 +227,11 @@ core_initcall(cma_init_reserved_areas);
  * called by board specific code when early allocator (memblock or bootmem)
  * is still activate.
  */
-int __init dma_declare_contiguous(struct device *dev, unsigned long size,
+int __init dma_declare_contiguous(struct device *dev, phys_addr_t size,
                                  phys_addr_t base, phys_addr_t limit)
 {
        struct cma_reserved *r = &cma_reserved[cma_reserved_count];
-       unsigned long alignment;
+       phys_addr_t alignment;
 
        pr_debug("%s(size %lx, base %08lx, limit %08lx)\n", __func__,
                 (unsigned long)size, (unsigned long)base,
@@ -271,10 +268,6 @@ int __init dma_declare_contiguous(struct device *dev, unsigned long size,
                if (!addr) {
                        base = -ENOMEM;
                        goto err;
-               } else if (addr + size > ~(unsigned long)0) {
-                       memblock_free(addr, size);
-                       base = -EINVAL;
-                       goto err;
                } else {
                        base = addr;
                }
@@ -288,14 +281,14 @@ int __init dma_declare_contiguous(struct device *dev, unsigned long size,
        r->size = size;
        r->dev = dev;
        cma_reserved_count++;
-       pr_info("CMA: reserved %ld MiB at %08lx\n", size / SZ_1M,
+       pr_info("CMA: reserved %ld MiB at %08lx\n", (unsigned long)size / SZ_1M,
                (unsigned long)base);
 
        /* Architecture specific contiguous memory fixup. */
        dma_contiguous_early_fixup(base, size);
        return 0;
 err:
-       pr_err("CMA: failed to reserve %ld MiB\n", size / SZ_1M);
+       pr_err("CMA: failed to reserve %ld MiB\n", (unsigned long)size / SZ_1M);
        return base;
 }
 
index 8154145..8945f4e 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 8727e9c..b2ee3bc 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
 #include <linux/idr.h>
+#include <linux/acpi.h>
 
 #include "base.h"
 #include "power/power.h"
@@ -83,9 +84,16 @@ EXPORT_SYMBOL_GPL(platform_get_resource);
  */
 int platform_get_irq(struct platform_device *dev, unsigned int num)
 {
+#ifdef CONFIG_SPARC
+       /* sparc does not have irqs represented as IORESOURCE_IRQ resources */
+       if (!dev || num >= dev->archdata.num_irqs)
+               return -ENXIO;
+       return dev->archdata.irqs[num];
+#else
        struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num);
 
        return r ? r->start : -ENXIO;
+#endif
 }
 EXPORT_SYMBOL_GPL(platform_get_irq);
 
@@ -429,6 +437,7 @@ struct platform_device *platform_device_register_full(
                goto err_alloc;
 
        pdev->dev.parent = pdevinfo->parent;
+       ACPI_HANDLE_SET(&pdev->dev, pdevinfo->acpi_node.handle);
 
        if (pdevinfo->dma_mask) {
                /*
@@ -459,6 +468,7 @@ struct platform_device *platform_device_register_full(
        ret = platform_device_add(pdev);
        if (ret) {
 err:
+               ACPI_HANDLE_SET(&pdev->dev, NULL);
                kfree(pdev->dev.dma_mask);
 
 err_alloc:
@@ -474,8 +484,16 @@ static int platform_drv_probe(struct device *_dev)
 {
        struct platform_driver *drv = to_platform_driver(_dev->driver);
        struct platform_device *dev = to_platform_device(_dev);
+       int ret;
+
+       if (ACPI_HANDLE(_dev))
+               acpi_dev_pm_attach(_dev, true);
 
-       return drv->probe(dev);
+       ret = drv->probe(dev);
+       if (ret && ACPI_HANDLE(_dev))
+               acpi_dev_pm_detach(_dev, true);
+
+       return ret;
 }
 
 static int platform_drv_probe_fail(struct device *_dev)
@@ -487,8 +505,13 @@ static int platform_drv_remove(struct device *_dev)
 {
        struct platform_driver *drv = to_platform_driver(_dev->driver);
        struct platform_device *dev = to_platform_device(_dev);
+       int ret;
 
-       return drv->remove(dev);
+       ret = drv->remove(dev);
+       if (ACPI_HANDLE(_dev))
+               acpi_dev_pm_detach(_dev, true);
+
+       return ret;
 }
 
 static void platform_drv_shutdown(struct device *_dev)
@@ -497,6 +520,8 @@ static void platform_drv_shutdown(struct device *_dev)
        struct platform_device *dev = to_platform_device(_dev);
 
        drv->shutdown(dev);
+       if (ACPI_HANDLE(_dev))
+               acpi_dev_pm_detach(_dev, true);
 }
 
 /**
@@ -702,6 +727,10 @@ static int platform_match(struct device *dev, struct device_driver *drv)
        if (of_driver_match_device(dev, drv))
                return 1;
 
+       /* Then try ACPI style match */
+       if (acpi_driver_match_device(dev, drv))
+               return 1;
+
        /* Then try to match against the id table */
        if (pdrv->id_table)
                return platform_match_id(pdrv->id_table, pdev) != NULL;
index eb78e96..9d8fde7 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 c22b869..acc3a8d 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 d946864..50b2831 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
@@ -512,7 +531,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();
+       kfree_rcu(opp, head);
 
        /* Notify the change of the OPP availability */
        if (availability_req)
@@ -522,13 +541,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 +568,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 +590,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 0dbfdf4..b16686a 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 74a67e0..ff46387 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"
 
@@ -48,6 +49,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,24 +220,28 @@ 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;
+       struct pm_qos_flags *f;
 
        /*
-        * If the device's PM QoS resume latency limit has been exposed to user
-        * space, it has to be hidden at this point.
+        * If the device's PM QoS resume latency limit or PM QoS flags have been
+        * exposed to user space, they have to be hidden at this point.
         */
        dev_pm_qos_hide_latency_limit(dev);
+       dev_pm_qos_hide_flags(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;
 
-       /* Flush the constraints list for the device */
-       plist_for_each_entry_safe(req, tmp, &c->list, node) {
+       /* Flush the constraints lists for the device. */
+       c = &qos->latency;
+       plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) {
                /*
                 * Update constraints list and call the notification
                 * callbacks if needed
@@ -189,13 +249,18 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
                apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
                memset(req, 0, sizeof(*req));
        }
+       f = &qos->flags;
+       list_for_each_entry_safe(req, tmp, &f->list, data.flr.node) {
+               apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
+               memset(req, 0, sizeof(*req));
+       }
 
        spin_lock_irq(&dev->power.lock);
-       dev->power.constraints = NULL;
+       dev->power.qos = NULL;
        spin_unlock_irq(&dev->power.lock);
 
        kfree(c->notifiers);
-       kfree(c);
+       kfree(qos);
 
  out:
        mutex_unlock(&dev_pm_qos_mtx);
@@ -205,6 +270,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
@@ -218,9 +284,12 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
  * -EINVAL in case of wrong parameters, -ENOMEM if there's not enough memory
  * to allocate for data structures, -ENODEV if the device has just been removed
  * from the system.
+ *
+ * Callers should ensure that the target device is not RPM_SUSPENDED before
+ * using this function for requests of type DEV_PM_QOS_FLAGS.
  */
 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 +304,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 +320,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);
@@ -262,6 +333,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
  * @new_value: defines the qos request
@@ -275,11 +377,13 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_add_request);
  * 0 if the aggregated constraint value has not changed,
  * -EINVAL in case of wrong parameters, -ENODEV if the device has been
  * removed from the system
+ *
+ * Callers should ensure that the target device is not RPM_SUSPENDED before
+ * using this function for requests of type DEV_PM_QOS_FLAGS.
  */
-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 +393,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;
-       }
-
+       ret = __dev_pm_qos_update_request(req, new_value);
        mutex_unlock(&dev_pm_qos_mtx);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_update_request);
@@ -315,6 +411,9 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_update_request);
  * 0 if the aggregated constraint value has not changed,
  * -EINVAL in case of wrong parameters, -ENODEV if the device has been
  * removed from the system
+ *
+ * Callers should ensure that the target device is not RPM_SUSPENDED before
+ * using this function for requests of type DEV_PM_QOS_FLAGS.
  */
 int dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
 {
@@ -329,7 +428,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 +461,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 +492,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,9 +548,10 @@ 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)
+       if (error < 0)
                req->dev = NULL;
 
        return error;
@@ -459,10 +559,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 +587,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 +613,92 @@ 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;
+
+       pm_runtime_get_sync(dev);
+       ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_FLAGS, val);
+       if (ret < 0)
+               goto fail;
+
+       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);
+
+fail:
+       pm_runtime_put(dev);
+       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);
+               pm_runtime_get_sync(dev);
+               __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
+               pm_runtime_put(dev);
+       }
+}
+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 b91dc6f..50d16e3 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 6be390b..f0d3054 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 432aeee..d865470 100644 (file)
@@ -158,9 +158,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);
        }
index f529407..824e09c 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.
@@ -166,8 +167,8 @@ config BLK_DEV_DAC960
          module will be called DAC960.
 
 config BLK_DEV_UMEM
-       tristate "Micro Memory MM5415 Battery Backed RAM support (EXPERIMENTAL)"
-       depends on PCI && EXPERIMENTAL
+       tristate "Micro Memory MM5415 Battery Backed RAM support"
+       depends on PCI
        ---help---
          Saying Y here will include support for the MM5415 family of
          battery backed (Non-volatile) RAM cards.
@@ -430,8 +431,8 @@ config CDROM_PKTCDVD_BUFFERS
          a disc is opened for writing.
 
 config CDROM_PKTCDVD_WCACHE
-       bool "Enable write caching (EXPERIMENTAL)"
-       depends on CDROM_PKTCDVD && EXPERIMENTAL
+       bool "Enable write caching"
+       depends on CDROM_PKTCDVD
        help
          If enabled, write caching will be set for the CD-R/W device. For now
          this option is dangerous unless the CD-RW media is known good, as we
@@ -508,8 +509,8 @@ config XEN_BLKDEV_BACKEND
 
 
 config VIRTIO_BLK
-       tristate "Virtio block driver (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && VIRTIO
+       tristate "Virtio block driver"
+       depends on VIRTIO
        ---help---
          This is the virtual block driver for virtio.  It can be used with
           lguest or QEMU based VMMs (like KVM or Xen).  Say Y or M.
@@ -528,7 +529,7 @@ config BLK_DEV_HD
 
 config BLK_DEV_RBD
        tristate "Rados block device (RBD)"
-       depends on INET && EXPERIMENTAL && BLOCK
+       depends on INET && BLOCK
        select CEPH_LIB
        select LIBCRC32C
        select CRYPTO_AES
index 3804a0a..9fe4f18 100644 (file)
@@ -935,7 +935,7 @@ aoe_end_request(struct aoedev *d, struct request *rq, int fastfail)
 
        /* cf. http://lkml.org/lkml/2006/10/31/28 */
        if (!fastfail)
-               q->request_fn(q);
+               __blk_run_queue(q);
 }
 
 static void
index b0f553b..ca83f96 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 17c675c..2ddd64a 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,28 +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;
+       destroy_workqueue(floppy_wq);
+       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);
+                       disks[drive]->queue = NULL;
                }
-               put_disk(disks[dr]);
+               put_disk(disks[drive]);
        }
        return err;
 }
@@ -4548,11 +4555,12 @@ static void __exit floppy_module_exit(void)
        unregister_blkdev(FLOPPY_MAJOR, "fd");
        platform_driver_unregister(&floppy_driver);
 
+       destroy_workqueue(floppy_wq);
+
        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]);
@@ -4572,7 +4580,6 @@ static void __exit floppy_module_exit(void)
 
        cancel_delayed_work_sync(&fd_timeout);
        cancel_delayed_work_sync(&fd_timer);
-       destroy_workqueue(floppy_wq);
 
        if (atomic_read(&usage_count))
                floppy_release_irq_and_dma();
index e9d594f..54046e5 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 f946d31..9694dd9 100644 (file)
@@ -559,7 +559,7 @@ static void mtip_timeout_function(unsigned long int data)
        struct mtip_cmd *command;
        int tag, cmdto_cnt = 0;
        unsigned int bit, group;
-       unsigned int num_command_slots = port->dd->slot_groups * 32;
+       unsigned int num_command_slots;
        unsigned long to, tagaccum[SLOTBITS_IN_LONGS];
 
        if (unlikely(!port))
@@ -572,6 +572,7 @@ static void mtip_timeout_function(unsigned long int data)
        }
        /* clear the tag accumulator */
        memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long));
+       num_command_slots = port->dd->slot_groups * 32;
 
        for (tag = 0; tag < num_command_slots; tag++) {
                /*
@@ -2035,8 +2036,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 +2046,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 +2092,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 +2218,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 &&
+                                       (outbuf[0] & MTIP_SEC_ERASE_MODE)) {
+               erasemode = 1;
+       }
+
+       mtip_set_timeout(dd, &fis, &timeout, erasemode);
 
        /* Determine the correct transfer size.*/
        if (force_single_sector)
@@ -2428,7 +2440,7 @@ static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd,
  * return value
  *     None
  */
-static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
+static void mtip_hw_submit_io(struct driver_data *dd, sector_t sector,
                              int nsect, int nents, int tag, void *callback,
                              void *data, int dir)
 {
@@ -2436,6 +2448,7 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
        struct mtip_port *port = dd->port;
        struct mtip_cmd *command = &port->commands[tag];
        int dma_dir = (dir == READ) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+       u64 start = sector;
 
        /* Map the scatter list for DMA access */
        nents = dma_map_sg(&dd->pdev->dev, command->sg, nents, dma_dir);
@@ -2454,8 +2467,12 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
        fis->opts        = 1 << 7;
        fis->command     =
                (dir == READ ? ATA_CMD_FPDMA_READ : ATA_CMD_FPDMA_WRITE);
-       *((unsigned int *) &fis->lba_low) = (start & 0xFFFFFF);
-       *((unsigned int *) &fis->lba_low_ex) = ((start >> 24) & 0xFFFFFF);
+       fis->lba_low     = start & 0xFF;
+       fis->lba_mid     = (start >> 8) & 0xFF;
+       fis->lba_hi      = (start >> 16) & 0xFF;
+       fis->lba_low_ex  = (start >> 24) & 0xFF;
+       fis->lba_mid_ex  = (start >> 32) & 0xFF;
+       fis->lba_hi_ex   = (start >> 40) & 0xFF;
        fis->device      = 1 << 6;
        fis->features    = nsect & 0xFF;
        fis->features_ex = (nsect >> 8) & 0xFF;
index 18627a1..b174264 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     0x2
+
 /* # of times to retry timed out/failed IOs */
 #define MTIP_MAX_RETRIES       2
 
@@ -152,14 +155,14 @@ enum {
        MTIP_DDF_REBUILD_FAILED_BIT = 8,
 };
 
-__packed struct smart_attr{
+struct smart_attr {
        u8 attr_id;
        u16 flags;
        u8 cur;
        u8 worst;
        u32 data;
        u8 res[3];
-};
+} __packed;
 
 /* Register Frame Information Structure (FIS), host to device. */
 struct host_to_dev_fis {
index 9ad3b5e..9a54623 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 4f66171..f58434c 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 fc2de55..b00000e 100644 (file)
@@ -67,6 +67,7 @@ static struct usb_device_id ath3k_table[] = {
        { USB_DEVICE(0x13d3, 0x3304) },
        { USB_DEVICE(0x0930, 0x0215) },
        { USB_DEVICE(0x0489, 0xE03D) },
+       { USB_DEVICE(0x0489, 0xE027) },
 
        /* Atheros AR9285 Malbec with sflash firmware */
        { USB_DEVICE(0x03F0, 0x311D) },
index debda27..ee82f2f 100644 (file)
@@ -124,6 +124,7 @@ static struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
        { USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
        { USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
+       { USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE },
 
        /* Atheros AR9285 Malbec with sflash firmware */
        { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
index ff63560..0c48b0e 100644 (file)
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
+#include <linux/platform_data/omap_ocp2scp.h>
+
+/**
+ * _count_resources - count for the number of resources
+ * @res: struct resource *
+ *
+ * Count and return the number of resources populated for the device that is
+ * connected to ocp2scp.
+ */
+static unsigned _count_resources(struct resource *res)
+{
+       int cnt = 0;
+
+       while (res->start != res->end) {
+               cnt++;
+               res++;
+       }
+
+       return cnt;
+}
 
 static int ocp2scp_remove_devices(struct device *dev, void *c)
 {
@@ -34,20 +54,62 @@ static int ocp2scp_remove_devices(struct device *dev, void *c)
 
 static int __devinit omap_ocp2scp_probe(struct platform_device *pdev)
 {
-       int                     ret;
-       struct device_node      *np = pdev->dev.of_node;
+       int ret;
+       unsigned res_cnt, i;
+       struct device_node *np = pdev->dev.of_node;
+       struct platform_device *pdev_child;
+       struct omap_ocp2scp_platform_data *pdata = pdev->dev.platform_data;
+       struct omap_ocp2scp_dev *dev;
 
        if (np) {
                ret = of_platform_populate(np, NULL, NULL, &pdev->dev);
                if (ret) {
-                       dev_err(&pdev->dev, "failed to add resources for ocp2scp child\n");
+                       dev_err(&pdev->dev,
+                           "failed to add resources for ocp2scp child\n");
                        goto err0;
                }
+       } else if (pdata) {
+               for (i = 0, dev = *pdata->devices; i < pdata->dev_cnt; i++,
+                   dev++) {
+                       res_cnt = _count_resources(dev->res);
+
+                       pdev_child = platform_device_alloc(dev->drv_name,
+                           PLATFORM_DEVID_AUTO);
+                       if (!pdev_child) {
+                               dev_err(&pdev->dev,
+                                 "failed to allocate mem for ocp2scp child\n");
+                               goto err0;
+                       }
+
+                       ret = platform_device_add_resources(pdev_child,
+                           dev->res, res_cnt);
+                       if (ret) {
+                               dev_err(&pdev->dev,
+                                "failed to add resources for ocp2scp child\n");
+                               goto err1;
+                       }
+
+                       pdev_child->dev.parent  = &pdev->dev;
+
+                       ret = platform_device_add(pdev_child);
+                       if (ret) {
+                               dev_err(&pdev->dev,
+                                  "failed to register ocp2scp child device\n");
+                               goto err1;
+                       }
+               }
+       } else {
+               dev_err(&pdev->dev, "OCP2SCP initialized without plat data\n");
+               return -EINVAL;
        }
+
        pm_runtime_enable(&pdev->dev);
 
        return 0;
 
+err1:
+       platform_device_put(pdev_child);
+
 err0:
        device_for_each_child(&pdev->dev, NULL, ocp2scp_remove_devices);
 
index d0b27a3..7ff1d0d 100644 (file)
@@ -52,7 +52,6 @@ obj-$(CONFIG_TELCLOCK)                += tlclk.o
 obj-$(CONFIG_MWAVE)            += mwave/
 obj-$(CONFIG_AGP)              += agp/
 obj-$(CONFIG_PCMCIA)           += pcmcia/
-obj-$(CONFIG_IPMI_HANDLER)     += ipmi/
 
 obj-$(CONFIG_HANGCHECK_TIMER)  += hangcheck-timer.o
 obj-$(CONFIG_TCG_TPM)          += tpm/
index e01f5ea..38390f7 100644 (file)
@@ -667,7 +667,7 @@ static int intel_gtt_init(void)
        gtt_map_size = intel_private.base.gtt_total_entries * 4;
 
        intel_private.gtt = NULL;
-       if (INTEL_GTT_GEN < 6)
+       if (INTEL_GTT_GEN < 6 && INTEL_GTT_GEN > 2)
                intel_private.gtt = ioremap_wc(intel_private.gtt_bus_addr,
                                               gtt_map_size);
        if (intel_private.gtt == NULL)
index fbd9b2b..c58ea9b 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 263567f..beec162 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 2c29942..a0c84bb 100644 (file)
@@ -1880,7 +1880,7 @@ int ipmi_request_supply_msgs(ipmi_user_t          user,
                             struct ipmi_recv_msg *supplied_recv,
                             int                  priority)
 {
-       unsigned char saddr, lun;
+       unsigned char saddr = 0, lun = 0;
        int           rv;
 
        if (!user)
index 83f85cf..32a6c7e 100644 (file)
@@ -2424,6 +2424,38 @@ static void ipmi_pci_cleanup(struct smi_info *info)
        pci_disable_device(pdev);
 }
 
+static int __devinit ipmi_pci_probe_regspacing(struct smi_info *info)
+{
+       if (info->si_type == SI_KCS) {
+               unsigned char   status;
+               int             regspacing;
+
+               info->io.regsize = DEFAULT_REGSIZE;
+               info->io.regshift = 0;
+               info->io_size = 2;
+               info->handlers = &kcs_smi_handlers;
+
+               /* detect 1, 4, 16byte spacing */
+               for (regspacing = DEFAULT_REGSPACING; regspacing <= 16;) {
+                       info->io.regspacing = regspacing;
+                       if (info->io_setup(info)) {
+                               dev_err(info->dev,
+                                       "Could not setup I/O space\n");
+                               return DEFAULT_REGSPACING;
+                       }
+                       /* write invalid cmd */
+                       info->io.outputb(&info->io, 1, 0x10);
+                       /* read status back */
+                       status = info->io.inputb(&info->io, 1);
+                       info->io_cleanup(info);
+                       if (status)
+                               return regspacing;
+                       regspacing *= 4;
+               }
+       }
+       return DEFAULT_REGSPACING;
+}
+
 static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
                                    const struct pci_device_id *ent)
 {
@@ -2476,8 +2508,8 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
        }
        info->io.addr_data = pci_resource_start(pdev, 0);
 
-       info->io.regspacing = DEFAULT_REGSPACING;
-       info->io.regsize = DEFAULT_REGSPACING;
+       info->io.regspacing = ipmi_pci_probe_regspacing(info);
+       info->io.regsize = DEFAULT_REGSIZE;
        info->io.regshift = 0;
 
        info->irq = pdev->irq;
index 0bb207e..54a3a6d 100644 (file)
@@ -285,7 +285,7 @@ static long raw_ctl_compat_ioctl(struct file *file, unsigned int cmd,
 
 static const struct file_operations raw_fops = {
        .read           = do_sync_read,
-       .aio_read       = blkdev_aio_read,
+       .aio_read       = generic_file_aio_read,
        .write          = do_sync_write,
        .aio_write      = blkdev_aio_write,
        .fsync          = blkdev_fsync,
index 320debb..9b4f011 100644 (file)
@@ -1456,7 +1456,7 @@ static int __devexit sonypi_remove(struct platform_device *dev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int old_camera_power;
 
 static int sonypi_suspend(struct device *dev)
index bace9e9..823f62d 100644 (file)
@@ -42,10 +42,12 @@ config COMMON_CLK_WM831X
 
 config COMMON_CLK_VERSATILE
        bool "Clock driver for ARM Reference designs"
-       depends on ARCH_INTEGRATOR || ARCH_REALVIEW
+       depends on ARCH_INTEGRATOR || ARCH_REALVIEW || ARCH_VEXPRESS
        ---help---
-          Supports clocking on ARM Reference designs Integrator/AP,
-         Integrator/CP, RealView PB1176, EB, PB11MP and PBX.
+          Supports clocking on ARM Reference designs:
+         - Integrator/AP and Integrator/CP
+         - RealView PB1176, EB, PB11MP and PBX
+         - Versatile Express
 
 config COMMON_CLK_MAX77686
        tristate "Clock driver for Maxim 77686 MFD"
@@ -53,4 +55,12 @@ config COMMON_CLK_MAX77686
        ---help---
          This driver supports Maxim 77686 crystal oscillator clock. 
 
+config CLK_TWL6040
+       tristate "External McPDM functional clock from twl6040"
+       depends on TWL6040_CORE
+       ---help---
+         Enable the external functional clock support on OMAP4+ platforms for
+         McPDM. McPDM module is using the external bit clock on the McPDM bus
+         as functional clock.
+
 endmenu
index 71a25b9..2701235 100644 (file)
@@ -23,3 +23,4 @@ obj-$(CONFIG_ARCH_VT8500)     += clk-vt8500.o
 # Chip specific
 obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
 obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
+obj-$(CONFIG_CLK_TWL6040)      += clk-twl6040.o
index 67ad16b..b61ee2c 100644 (file)
@@ -33,17 +33,17 @@ void __init bcm2835_init_clocks(void)
 
        clk = clk_register_fixed_rate(NULL, "sys_pclk", NULL, CLK_IS_ROOT,
                                        250000000);
-       if (!clk)
+       if (IS_ERR(clk))
                pr_err("sys_pclk not registered\n");
 
        clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT,
                                        126000000);
-       if (!clk)
+       if (IS_ERR(clk))
                pr_err("apb_pclk not registered\n");
 
        clk = clk_register_fixed_rate(NULL, "uart0_pclk", NULL, CLK_IS_ROOT,
                                        3000000);
-       if (!clk)
+       if (IS_ERR(clk))
                pr_err("uart0_pclk not registered\n");
        ret = clk_register_clkdev(clk, NULL, "20201000.uart");
        if (ret)
@@ -51,7 +51,7 @@ void __init bcm2835_init_clocks(void)
 
        clk = clk_register_fixed_rate(NULL, "uart1_pclk", NULL, CLK_IS_ROOT,
                                        125000000);
-       if (!clk)
+       if (IS_ERR(clk))
                pr_err("uart1_pclk not registered\n");
        ret = clk_register_clkdev(clk, NULL, "20215000.uart");
        if (ret)
index f5ec0ee..af78ed6 100644 (file)
@@ -97,7 +97,7 @@ void __init of_fixed_clk_setup(struct device_node *node)
        of_property_read_string(node, "clock-output-names", &clk_name);
 
        clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT, rate);
-       if (clk)
+       if (!IS_ERR(clk))
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
 }
 EXPORT_SYMBOL_GPL(of_fixed_clk_setup);
index 517874f..a203ecc 100644 (file)
@@ -1054,118 +1054,118 @@ void __init sirfsoc_of_clk_init(void)
        /* These are always available (RTC and 26MHz OSC)*/
        clk = clk_register_fixed_rate(NULL, "rtc", NULL,
                CLK_IS_ROOT, 32768);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk = clk_register_fixed_rate(NULL, "osc", NULL,
                CLK_IS_ROOT, 26000000);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
 
        clk = clk_register(NULL, &clk_pll1.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk = clk_register(NULL, &clk_pll2.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk = clk_register(NULL, &clk_pll3.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk = clk_register(NULL, &clk_mem.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk = clk_register(NULL, &clk_sys.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk = clk_register(NULL, &clk_security.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "b8030000.security");
        clk = clk_register(NULL, &clk_dsp.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk = clk_register(NULL, &clk_gps.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "a8010000.gps");
        clk = clk_register(NULL, &clk_mf.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk = clk_register(NULL, &clk_io.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "io");
        clk = clk_register(NULL, &clk_cpu.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "cpu");
        clk = clk_register(NULL, &clk_uart0.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "b0050000.uart");
        clk = clk_register(NULL, &clk_uart1.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "b0060000.uart");
        clk = clk_register(NULL, &clk_uart2.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "b0070000.uart");
        clk = clk_register(NULL, &clk_tsc.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "b0110000.tsc");
        clk = clk_register(NULL, &clk_i2c0.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "b00e0000.i2c");
        clk = clk_register(NULL, &clk_i2c1.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "b00f0000.i2c");
        clk = clk_register(NULL, &clk_spi0.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "b00d0000.spi");
        clk = clk_register(NULL, &clk_spi1.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "b0170000.spi");
        clk = clk_register(NULL, &clk_pwmc.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "b0130000.pwm");
        clk = clk_register(NULL, &clk_efuse.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "b0140000.efusesys");
        clk = clk_register(NULL, &clk_pulse.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "b0150000.pulsec");
        clk = clk_register(NULL, &clk_dmac0.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "b00b0000.dma-controller");
        clk = clk_register(NULL, &clk_dmac1.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "b0160000.dma-controller");
        clk = clk_register(NULL, &clk_nand.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "b0030000.nand");
        clk = clk_register(NULL, &clk_audio.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "b0040000.audio");
        clk = clk_register(NULL, &clk_usp0.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "b0080000.usp");
        clk = clk_register(NULL, &clk_usp1.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "b0090000.usp");
        clk = clk_register(NULL, &clk_usp2.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "b00a0000.usp");
        clk = clk_register(NULL, &clk_vip.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "b00c0000.vip");
        clk = clk_register(NULL, &clk_gfx.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "98000000.graphics");
        clk = clk_register(NULL, &clk_mm.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "a0000000.multimedia");
        clk = clk_register(NULL, &clk_lcd.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "90010000.display");
        clk = clk_register(NULL, &clk_vpp.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "90020000.vpp");
        clk = clk_register(NULL, &clk_mmc01.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk = clk_register(NULL, &clk_mmc23.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk = clk_register(NULL, &clk_mmc45.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk = clk_register(NULL, &usb_pll_clk_hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk = clk_register(NULL, &clk_usb0.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "b00e0000.usb");
        clk = clk_register(NULL, &clk_usb1.hw);
-       BUG_ON(!clk);
+       BUG_ON(IS_ERR(clk));
        clk_register_clkdev(clk, NULL, "b00f0000.usb");
 }
diff --git a/drivers/clk/clk-twl6040.c b/drivers/clk/clk-twl6040.c
new file mode 100644 (file)
index 0000000..bc1e713
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+* TWL6040 clock module driver for OMAP4 McPDM functional clock
+*
+* Copyright (C) 2012 Texas Instruments Inc.
+* Peter Ujfalusi <peter.ujfalusi@ti.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.
+*
+* 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/clk.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/twl6040.h>
+#include <linux/clk-provider.h>
+
+struct twl6040_clk {
+       struct twl6040 *twl6040;
+       struct device *dev;
+       struct clk_hw mcpdm_fclk;
+       struct clk *clk;
+       int enabled;
+};
+
+static int twl6040_bitclk_is_enabled(struct clk_hw *hw)
+{
+       struct twl6040_clk *twl6040_clk = container_of(hw, struct twl6040_clk,
+                                                      mcpdm_fclk);
+       return twl6040_clk->enabled;
+}
+
+static int twl6040_bitclk_prepare(struct clk_hw *hw)
+{
+       struct twl6040_clk *twl6040_clk = container_of(hw, struct twl6040_clk,
+                                                      mcpdm_fclk);
+       int ret;
+
+       ret = twl6040_power(twl6040_clk->twl6040, 1);
+       if (!ret)
+               twl6040_clk->enabled = 1;
+
+       return ret;
+}
+
+static void twl6040_bitclk_unprepare(struct clk_hw *hw)
+{
+       struct twl6040_clk *twl6040_clk = container_of(hw, struct twl6040_clk,
+                                                      mcpdm_fclk);
+       int ret;
+
+       ret = twl6040_power(twl6040_clk->twl6040, 0);
+       if (!ret)
+               twl6040_clk->enabled = 0;
+}
+
+static const struct clk_ops twl6040_mcpdm_ops = {
+       .is_enabled = twl6040_bitclk_is_enabled,
+       .prepare = twl6040_bitclk_prepare,
+       .unprepare = twl6040_bitclk_unprepare,
+};
+
+static struct clk_init_data wm831x_clkout_init = {
+       .name = "mcpdm_fclk",
+       .ops = &twl6040_mcpdm_ops,
+       .flags = CLK_IS_ROOT,
+};
+
+static int __devinit twl6040_clk_probe(struct platform_device *pdev)
+{
+       struct twl6040 *twl6040 = dev_get_drvdata(pdev->dev.parent);
+       struct twl6040_clk *clkdata;
+
+       clkdata = devm_kzalloc(&pdev->dev, sizeof(*clkdata), GFP_KERNEL);
+       if (!clkdata)
+               return -ENOMEM;
+
+       clkdata->dev = &pdev->dev;
+       clkdata->twl6040 = twl6040;
+
+       clkdata->mcpdm_fclk.init = &wm831x_clkout_init;
+       clkdata->clk = clk_register(&pdev->dev, &clkdata->mcpdm_fclk);
+       if (IS_ERR(clkdata->clk))
+               return PTR_ERR(clkdata->clk);
+
+       dev_set_drvdata(&pdev->dev, clkdata);
+
+       return 0;
+}
+
+static int __devexit twl6040_clk_remove(struct platform_device *pdev)
+{
+       struct twl6040_clk *clkdata = dev_get_drvdata(&pdev->dev);
+
+       clk_unregister(clkdata->clk);
+
+       return 0;
+}
+
+static struct platform_driver twl6040_clk_driver = {
+       .driver = {
+               .name = "twl6040-clk",
+               .owner = THIS_MODULE,
+       },
+       .probe = twl6040_clk_probe,
+       .remove = __devexit_p(twl6040_clk_remove),
+};
+
+module_platform_driver(twl6040_clk_driver);
+
+MODULE_DESCRIPTION("TWL6040 clock driver for McPDM functional clock");
+MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
+MODULE_ALIAS("platform:twl6040-clk");
+MODULE_LICENSE("GPL");
index a885600..fe25570 100644 (file)
@@ -120,8 +120,17 @@ static unsigned long vt8500_dclk_recalc_rate(struct clk_hw *hw,
 static long vt8500_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
                                unsigned long *prate)
 {
+       struct clk_device *cdev = to_clk_device(hw);
        u32 divisor = *prate / rate;
 
+       /*
+        * If this is a request for SDMMC we have to adjust the divisor
+        * when >31 to use the fixed predivisor
+        */
+       if ((cdev->div_mask == 0x3F) && (divisor > 31)) {
+               divisor = 64 * ((divisor / 64) + 1);
+       }
+
        return *prate / divisor;
 }
 
@@ -135,6 +144,15 @@ static int vt8500_dclk_set_rate(struct clk_hw *hw, unsigned long rate,
        if (divisor == cdev->div_mask + 1)
                divisor = 0;
 
+       /* SDMMC mask may need to be corrected before testing if its valid */
+       if ((cdev->div_mask == 0x3F) && (divisor > 31)) {
+               /*
+                * Bit 5 is a fixed /64 predivisor. If the requested divisor
+                * is >31 then correct for the fixed divisor being required.
+                */
+               divisor = 0x20 + (divisor / 64);
+       }
+
        if (divisor > cdev->div_mask) {
                pr_err("%s: invalid divisor for clock\n", __func__);
                return -EINVAL;
index e7b7765..db4fbf2 100644 (file)
@@ -370,43 +370,27 @@ static __devinit int wm831x_clk_probe(struct platform_device *pdev)
        clkdata->xtal_ena = ret & WM831X_XTAL_ENA;
 
        clkdata->xtal_hw.init = &wm831x_xtal_init;
-       clkdata->xtal = clk_register(&pdev->dev, &clkdata->xtal_hw);
-       if (!clkdata->xtal)
-               return -EINVAL;
+       clkdata->xtal = devm_clk_register(&pdev->dev, &clkdata->xtal_hw);
+       if (IS_ERR(clkdata->xtal))
+               return PTR_ERR(clkdata->xtal);
 
        clkdata->fll_hw.init = &wm831x_fll_init;
-       clkdata->fll = clk_register(&pdev->dev, &clkdata->fll_hw);
-       if (!clkdata->fll) {
-               ret = -EINVAL;
-               goto err_xtal;
-       }
+       clkdata->fll = devm_clk_register(&pdev->dev, &clkdata->fll_hw);
+       if (IS_ERR(clkdata->fll))
+               return PTR_ERR(clkdata->fll);
 
        clkdata->clkout_hw.init = &wm831x_clkout_init;
-       clkdata->clkout = clk_register(&pdev->dev, &clkdata->clkout_hw);
-       if (!clkdata->clkout) {
-               ret = -EINVAL;
-               goto err_fll;
-       }
+       clkdata->clkout = devm_clk_register(&pdev->dev, &clkdata->clkout_hw);
+       if (IS_ERR(clkdata->clkout))
+               return PTR_ERR(clkdata->clkout);
 
        dev_set_drvdata(&pdev->dev, clkdata);
 
        return 0;
-
-err_fll:
-       clk_unregister(clkdata->fll);
-err_xtal:
-       clk_unregister(clkdata->xtal);
-       return ret;
 }
 
 static int __devexit wm831x_clk_remove(struct platform_device *pdev)
 {
-       struct wm831x_clk *clkdata = dev_get_drvdata(&pdev->dev);
-
-       clk_unregister(clkdata->clkout);
-       clk_unregister(clkdata->fll);
-       clk_unregister(clkdata->xtal);
-
        return 0;
 }
 
index 56e4495..251e45d 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include <linux/device.h>
 
 static DEFINE_SPINLOCK(enable_lock);
 static DEFINE_MUTEX(prepare_lock);
@@ -218,8 +219,17 @@ static void clk_disable_unused_subtree(struct clk *clk)
        if (clk->flags & CLK_IGNORE_UNUSED)
                goto unlock_out;
 
-       if (__clk_is_enabled(clk) && clk->ops->disable)
-               clk->ops->disable(clk->hw);
+       /*
+        * some gate clocks have special needs during the disable-unused
+        * sequence.  call .disable_unused if available, otherwise fall
+        * back to .disable
+        */
+       if (__clk_is_enabled(clk)) {
+               if (clk->ops->disable_unused)
+                       clk->ops->disable_unused(clk->hw);
+               else if (clk->ops->disable)
+                       clk->ops->disable(clk->hw);
+       }
 
 unlock_out:
        spin_unlock_irqrestore(&enable_lock, flags);
@@ -261,7 +271,7 @@ inline struct clk_hw *__clk_get_hw(struct clk *clk)
 
 inline u8 __clk_get_num_parents(struct clk *clk)
 {
-       return !clk ? -EINVAL : clk->num_parents;
+       return !clk ? 0 : clk->num_parents;
 }
 
 inline struct clk *__clk_get_parent(struct clk *clk)
@@ -269,14 +279,14 @@ inline struct clk *__clk_get_parent(struct clk *clk)
        return !clk ? NULL : clk->parent;
 }
 
-inline int __clk_get_enable_count(struct clk *clk)
+inline unsigned int __clk_get_enable_count(struct clk *clk)
 {
-       return !clk ? -EINVAL : clk->enable_count;
+       return !clk ? 0 : clk->enable_count;
 }
 
-inline int __clk_get_prepare_count(struct clk *clk)
+inline unsigned int __clk_get_prepare_count(struct clk *clk)
 {
-       return !clk ? -EINVAL : clk->prepare_count;
+       return !clk ? 0 : clk->prepare_count;
 }
 
 unsigned long __clk_get_rate(struct clk *clk)
@@ -302,15 +312,15 @@ out:
 
 inline unsigned long __clk_get_flags(struct clk *clk)
 {
-       return !clk ? -EINVAL : clk->flags;
+       return !clk ? 0 : clk->flags;
 }
 
-int __clk_is_enabled(struct clk *clk)
+bool __clk_is_enabled(struct clk *clk)
 {
        int ret;
 
        if (!clk)
-               return -EINVAL;
+               return false;
 
        /*
         * .is_enabled is only mandatory for clocks that gate
@@ -323,7 +333,7 @@ int __clk_is_enabled(struct clk *clk)
 
        ret = clk->ops->is_enabled(clk->hw);
 out:
-       return ret;
+       return !!ret;
 }
 
 static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
@@ -568,7 +578,7 @@ unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
        unsigned long parent_rate = 0;
 
        if (!clk)
-               return -EINVAL;
+               return 0;
 
        if (!clk->ops->round_rate) {
                if (clk->flags & CLK_SET_RATE_PARENT)
@@ -1297,12 +1307,20 @@ int __clk_init(struct device *dev, struct clk *clk)
         * walk the list of orphan clocks and reparent any that are children of
         * this clock
         */
-       hlist_for_each_entry_safe(orphan, tmp, tmp2, &clk_orphan_list, child_node)
+       hlist_for_each_entry_safe(orphan, tmp, tmp2, &clk_orphan_list, child_node) {
+               if (orphan->ops->get_parent) {
+                       i = orphan->ops->get_parent(orphan->hw);
+                       if (!strcmp(clk->name, orphan->parent_names[i]))
+                               __clk_reparent(orphan, clk);
+                       continue;
+               }
+
                for (i = 0; i < orphan->num_parents; i++)
                        if (!strcmp(clk->name, orphan->parent_names[i])) {
                                __clk_reparent(orphan, clk);
                                break;
                        }
+        }
 
        /*
         * optional platform-specific magic
@@ -1361,28 +1379,9 @@ struct clk *__clk_register(struct device *dev, struct clk_hw *hw)
 }
 EXPORT_SYMBOL_GPL(__clk_register);
 
-/**
- * clk_register - allocate a new clock, register it and return an opaque cookie
- * @dev: device that is registering this clock
- * @hw: link to hardware-specific clock data
- *
- * clk_register is the primary interface for populating the clock tree with new
- * clock nodes.  It returns a pointer to the newly allocated struct clk which
- * cannot be dereferenced by driver code but may be used in conjuction with the
- * rest of the clock API.  In the event of an error clk_register will return an
- * error code; drivers must test for an error code after calling clk_register.
- */
-struct clk *clk_register(struct device *dev, struct clk_hw *hw)
+static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk)
 {
        int i, ret;
-       struct clk *clk;
-
-       clk = kzalloc(sizeof(*clk), GFP_KERNEL);
-       if (!clk) {
-               pr_err("%s: could not allocate clk\n", __func__);
-               ret = -ENOMEM;
-               goto fail_out;
-       }
 
        clk->name = kstrdup(hw->init->name, GFP_KERNEL);
        if (!clk->name) {
@@ -1420,7 +1419,7 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 
        ret = __clk_init(dev, clk);
        if (!ret)
-               return clk;
+               return 0;
 
 fail_parent_names_copy:
        while (--i >= 0)
@@ -1429,6 +1428,36 @@ fail_parent_names_copy:
 fail_parent_names:
        kfree(clk->name);
 fail_name:
+       return ret;
+}
+
+/**
+ * clk_register - allocate a new clock, register it and return an opaque cookie
+ * @dev: device that is registering this clock
+ * @hw: link to hardware-specific clock data
+ *
+ * clk_register is the primary interface for populating the clock tree with new
+ * clock nodes.  It returns a pointer to the newly allocated struct clk which
+ * cannot be dereferenced by driver code but may be used in conjuction with the
+ * rest of the clock API.  In the event of an error clk_register will return an
+ * error code; drivers must test for an error code after calling clk_register.
+ */
+struct clk *clk_register(struct device *dev, struct clk_hw *hw)
+{
+       int ret;
+       struct clk *clk;
+
+       clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+       if (!clk) {
+               pr_err("%s: could not allocate clk\n", __func__);
+               ret = -ENOMEM;
+               goto fail_out;
+       }
+
+       ret = _clk_register(dev, hw, clk);
+       if (!ret)
+               return clk;
+
        kfree(clk);
 fail_out:
        return ERR_PTR(ret);
@@ -1444,6 +1473,63 @@ EXPORT_SYMBOL_GPL(clk_register);
 void clk_unregister(struct clk *clk) {}
 EXPORT_SYMBOL_GPL(clk_unregister);
 
+static void devm_clk_release(struct device *dev, void *res)
+{
+       clk_unregister(res);
+}
+
+/**
+ * devm_clk_register - resource managed clk_register()
+ * @dev: device that is registering this clock
+ * @hw: link to hardware-specific clock data
+ *
+ * Managed clk_register(). Clocks returned from this function are
+ * automatically clk_unregister()ed on driver detach. See clk_register() for
+ * more information.
+ */
+struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw)
+{
+       struct clk *clk;
+       int ret;
+
+       clk = devres_alloc(devm_clk_release, sizeof(*clk), GFP_KERNEL);
+       if (!clk)
+               return ERR_PTR(-ENOMEM);
+
+       ret = _clk_register(dev, hw, clk);
+       if (!ret) {
+               devres_add(dev, clk);
+       } else {
+               devres_free(clk);
+               clk = ERR_PTR(ret);
+       }
+
+       return clk;
+}
+EXPORT_SYMBOL_GPL(devm_clk_register);
+
+static int devm_clk_match(struct device *dev, void *res, void *data)
+{
+       struct clk *c = res;
+       if (WARN_ON(!c))
+               return 0;
+       return c == data;
+}
+
+/**
+ * devm_clk_unregister - resource managed clk_unregister()
+ * @clk: clock to unregister
+ *
+ * Deallocate a clock allocated with devm_clk_register(). Normally
+ * this function will not need to be called and the resource management
+ * code will ensure that the resource is freed.
+ */
+void devm_clk_unregister(struct device *dev, struct clk *clk)
+{
+       WARN_ON(devres_release(dev, devm_clk_release, devm_clk_match, clk));
+}
+EXPORT_SYMBOL_GPL(devm_clk_unregister);
+
 /***        clk rate change notifiers        ***/
 
 /**
index f00dffb..8dd476e 100644 (file)
@@ -85,7 +85,7 @@ enum imx23_clk {
        cpu_xtal, hbus, xbus, lcdif_div, ssp_div, gpmi_div, emi_pll,
        emi_xtal, etm_div, saif_div, clk32k_div, rtc, adc, spdif_div,
        clk32k, dri, pwm, filt, uart, ssp, gpmi, spdif, emi, saif,
-       lcdif, etm, usb, usb_pwr,
+       lcdif, etm, usb, usb_phy,
        clk_max
 };
 
@@ -143,8 +143,8 @@ int __init mx23_clocks_init(void)
        clks[saif] = mxs_clk_gate("saif", "saif_div", SAIF, 31);
        clks[lcdif] = mxs_clk_gate("lcdif", "lcdif_div", PIX, 31);
        clks[etm] = mxs_clk_gate("etm", "etm_div", ETM, 31);
-       clks[usb] = mxs_clk_gate("usb", "usb_pwr", DIGCTRL, 2);
-       clks[usb_pwr] = clk_register_gate(NULL, "usb_pwr", "pll", 0, PLLCTRL0, 18, 0, &mxs_lock);
+       clks[usb] = mxs_clk_gate("usb", "usb_phy", DIGCTRL, 2);
+       clks[usb_phy] = clk_register_gate(NULL, "usb_phy", "pll", 0, PLLCTRL0, 18, 0, &mxs_lock);
 
        for (i = 0; i < ARRAY_SIZE(clks); i++)
                if (IS_ERR(clks[i])) {
index 42978f1..db3af08 100644 (file)
@@ -140,7 +140,7 @@ enum imx28_clk {
        emi_xtal, lcdif_div, etm_div, ptp, saif0_div, saif1_div,
        clk32k_div, rtc, lradc, spdif_div, clk32k, pwm, uart, ssp0,
        ssp1, ssp2, ssp3, gpmi, spdif, emi, saif0, saif1, lcdif, etm,
-       fec, can0, can1, usb0, usb1, usb0_pwr, usb1_pwr, enet_out,
+       fec, can0, can1, usb0, usb1, usb0_phy, usb1_phy, enet_out,
        clk_max
 };
 
@@ -218,10 +218,10 @@ int __init mx28_clocks_init(void)
        clks[fec] = mxs_clk_gate("fec", "hbus", ENET, 30);
        clks[can0] = mxs_clk_gate("can0", "ref_xtal", FLEXCAN, 30);
        clks[can1] = mxs_clk_gate("can1", "ref_xtal", FLEXCAN, 28);
-       clks[usb0] = mxs_clk_gate("usb0", "usb0_pwr", DIGCTRL, 2);
-       clks[usb1] = mxs_clk_gate("usb1", "usb1_pwr", DIGCTRL, 16);
-       clks[usb0_pwr] = clk_register_gate(NULL, "usb0_pwr", "pll0", 0, PLL0CTRL0, 18, 0, &mxs_lock);
-       clks[usb1_pwr] = clk_register_gate(NULL, "usb1_pwr", "pll1", 0, PLL1CTRL0, 18, 0, &mxs_lock);
+       clks[usb0] = mxs_clk_gate("usb0", "usb0_phy", DIGCTRL, 2);
+       clks[usb1] = mxs_clk_gate("usb1", "usb1_phy", DIGCTRL, 16);
+       clks[usb0_phy] = clk_register_gate(NULL, "usb0_phy", "pll0", 0, PLL0CTRL0, 18, 0, &mxs_lock);
+       clks[usb1_phy] = clk_register_gate(NULL, "usb1_phy", "pll1", 0, PLL1CTRL0, 18, 0, &mxs_lock);
        clks[enet_out] = clk_register_gate(NULL, "enet_out", "pll2", 0, ENET, 18, 0, &mxs_lock);
 
        for (i = 0; i < ARRAY_SIZE(clks); i++)
index 6756e7c..bdfb442 100644 (file)
@@ -179,7 +179,8 @@ struct clk *clk_register_aux(const char *aux_name, const char *gate_name,
        if (gate_name) {
                struct clk *tgate_clk;
 
-               tgate_clk = clk_register_gate(NULL, gate_name, aux_name, 0, reg,
+               tgate_clk = clk_register_gate(NULL, gate_name, aux_name,
+                               CLK_SET_RATE_PARENT, reg,
                                aux->masks->enable_bit, 0, lock);
                if (IS_ERR_OR_NULL(tgate_clk))
                        goto free_aux;
index 5f1b6ba..1b9b65b 100644 (file)
@@ -147,7 +147,7 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long drate,
        struct clk_pll *pll = to_clk_pll(hw);
        struct pll_rate_tbl *rtbl = pll->vco->rtbl;
        unsigned long flags = 0, val;
-       int i;
+       int uninitialized_var(i);
 
        clk_pll_round_rate_index(hw, drate, NULL, &i);
 
index 7cd6378..628b6d5 100644 (file)
@@ -32,5 +32,8 @@ long clk_round_rate_index(struct clk_hw *hw, unsigned long drate,
                }
        }
 
+       if ((*index) == rtbl_cnt)
+               (*index)--;
+
        return rate;
 }
index 0fcec2a..147e25f 100644 (file)
@@ -313,6 +313,20 @@ static struct aux_clk_masks i2s_sclk_masks = {
 /* i2s prs1 aux rate configuration table, in ascending order of rates */
 static struct aux_rate_tbl i2s_prs1_rtbl[] = {
        /* For parent clk = 49.152 MHz */
+       {.xscale = 1, .yscale = 12, .eq = 0}, /* 2.048 MHz, smp freq = 8Khz */
+       {.xscale = 11, .yscale = 96, .eq = 0}, /* 2.816 MHz, smp freq = 11Khz */
+       {.xscale = 1, .yscale = 6, .eq = 0}, /* 4.096 MHz, smp freq = 16Khz */
+       {.xscale = 11, .yscale = 48, .eq = 0}, /* 5.632 MHz, smp freq = 22Khz */
+
+       /*
+        * with parent clk = 49.152, freq gen is 8.192 MHz, smp freq = 32Khz
+        * with parent clk = 12.288, freq gen is 2.048 MHz, smp freq = 8Khz
+        */
+       {.xscale = 1, .yscale = 3, .eq = 0},
+
+       /* For parent clk = 49.152 MHz */
+       {.xscale = 17, .yscale = 37, .eq = 0}, /* 11.289 MHz, smp freq = 44Khz*/
+
        {.xscale = 1, .yscale = 2, .eq = 0}, /* 12.288 MHz */
 };
 
@@ -374,9 +388,6 @@ void __init spear1310_clk_init(void)
 {
        struct clk *clk, *clk1;
 
-       clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
-       clk_register_clkdev(clk, "apb_pclk", NULL);
-
        clk = clk_register_fixed_rate(NULL, "osc_32k_clk", NULL, CLK_IS_ROOT,
                        32000);
        clk_register_clkdev(clk, "osc_32k_clk", NULL);
@@ -401,7 +412,7 @@ void __init spear1310_clk_init(void)
        clk = clk_register_gate(NULL, "rtc-spear", "osc_32k_clk", 0,
                        SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_RTC_CLK_ENB, 0,
                        &_lock);
-       clk_register_clkdev(clk, NULL, "fc900000.rtc");
+       clk_register_clkdev(clk, NULL, "e0580000.rtc");
 
        /* clock derived from 24 or 25 MHz osc clk */
        /* vco-pll */
@@ -483,13 +494,18 @@ void __init spear1310_clk_init(void)
        clk_register_clkdev(clk, "ddr_clk", NULL);
 
        /* clock derived from pll1 clk */
-       clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk", 0, 1, 2);
+       clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk",
+                       CLK_SET_RATE_PARENT, 1, 2);
        clk_register_clkdev(clk, "cpu_clk", NULL);
 
        clk = clk_register_fixed_factor(NULL, "wdt_clk", "cpu_clk", 0, 1,
                        2);
        clk_register_clkdev(clk, NULL, "ec800620.wdt");
 
+       clk = clk_register_fixed_factor(NULL, "smp_twd_clk", "cpu_clk", 0, 1,
+                       2);
+       clk_register_clkdev(clk, NULL, "smp_twd");
+
        clk = clk_register_fixed_factor(NULL, "ahb_clk", "pll1_clk", 0, 1,
                        6);
        clk_register_clkdev(clk, "ahb_clk", NULL);
@@ -547,14 +563,14 @@ void __init spear1310_clk_init(void)
        clk_register_clkdev(clk1, "uart_syn_gclk", NULL);
 
        clk = clk_register_mux(NULL, "uart0_mclk", uart0_parents,
-                       ARRAY_SIZE(uart0_parents), 0, SPEAR1310_PERIP_CLK_CFG,
-                       SPEAR1310_UART_CLK_SHIFT, SPEAR1310_UART_CLK_MASK, 0,
-                       &_lock);
+                       ARRAY_SIZE(uart0_parents), CLK_SET_RATE_PARENT,
+                       SPEAR1310_PERIP_CLK_CFG, SPEAR1310_UART_CLK_SHIFT,
+                       SPEAR1310_UART_CLK_MASK, 0, &_lock);
        clk_register_clkdev(clk, "uart0_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "uart0_clk", "uart0_mclk", 0,
-                       SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_UART_CLK_ENB, 0,
-                       &_lock);
+       clk = clk_register_gate(NULL, "uart0_clk", "uart0_mclk",
+                       CLK_SET_RATE_PARENT, SPEAR1310_PERIP1_CLK_ENB,
+                       SPEAR1310_UART_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, NULL, "e0000000.serial");
 
        clk = clk_register_aux("sdhci_syn_clk", "sdhci_syn_gclk",
@@ -563,9 +579,9 @@ void __init spear1310_clk_init(void)
        clk_register_clkdev(clk, "sdhci_syn_clk", NULL);
        clk_register_clkdev(clk1, "sdhci_syn_gclk", NULL);
 
-       clk = clk_register_gate(NULL, "sdhci_clk", "sdhci_syn_gclk", 0,
-                       SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_SDHCI_CLK_ENB, 0,
-                       &_lock);
+       clk = clk_register_gate(NULL, "sdhci_clk", "sdhci_syn_gclk",
+                       CLK_SET_RATE_PARENT, SPEAR1310_PERIP1_CLK_ENB,
+                       SPEAR1310_SDHCI_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, NULL, "b3000000.sdhci");
 
        clk = clk_register_aux("cfxd_syn_clk", "cfxd_syn_gclk", "vco1div2_clk",
@@ -574,9 +590,9 @@ void __init spear1310_clk_init(void)
        clk_register_clkdev(clk, "cfxd_syn_clk", NULL);
        clk_register_clkdev(clk1, "cfxd_syn_gclk", NULL);
 
-       clk = clk_register_gate(NULL, "cfxd_clk", "cfxd_syn_gclk", 0,
-                       SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_CFXD_CLK_ENB, 0,
-                       &_lock);
+       clk = clk_register_gate(NULL, "cfxd_clk", "cfxd_syn_gclk",
+                       CLK_SET_RATE_PARENT, SPEAR1310_PERIP1_CLK_ENB,
+                       SPEAR1310_CFXD_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, NULL, "b2800000.cf");
        clk_register_clkdev(clk, NULL, "arasan_xd");
 
@@ -587,9 +603,9 @@ void __init spear1310_clk_init(void)
        clk_register_clkdev(clk1, "c3_syn_gclk", NULL);
 
        clk = clk_register_mux(NULL, "c3_mclk", c3_parents,
-                       ARRAY_SIZE(c3_parents), 0, SPEAR1310_PERIP_CLK_CFG,
-                       SPEAR1310_C3_CLK_SHIFT, SPEAR1310_C3_CLK_MASK, 0,
-                       &_lock);
+                       ARRAY_SIZE(c3_parents), CLK_SET_RATE_PARENT,
+                       SPEAR1310_PERIP_CLK_CFG, SPEAR1310_C3_CLK_SHIFT,
+                       SPEAR1310_C3_CLK_MASK, 0, &_lock);
        clk_register_clkdev(clk, "c3_mclk", NULL);
 
        clk = clk_register_gate(NULL, "c3_clk", "c3_mclk", 0,
@@ -615,7 +631,7 @@ void __init spear1310_clk_init(void)
                        ARRAY_SIZE(gmac_phy_parents), 0,
                        SPEAR1310_PERIP_CLK_CFG, SPEAR1310_GMAC_PHY_CLK_SHIFT,
                        SPEAR1310_GMAC_PHY_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, NULL, "stmmacphy.0");
+       clk_register_clkdev(clk, "stmmacphy.0", NULL);
 
        /* clcd */
        clk = clk_register_mux(NULL, "clcd_syn_mclk", clcd_synth_parents,
@@ -630,22 +646,22 @@ void __init spear1310_clk_init(void)
        clk_register_clkdev(clk, "clcd_syn_clk", NULL);
 
        clk = clk_register_mux(NULL, "clcd_pixel_mclk", clcd_pixel_parents,
-                       ARRAY_SIZE(clcd_pixel_parents), 0,
+                       ARRAY_SIZE(clcd_pixel_parents), CLK_SET_RATE_PARENT,
                        SPEAR1310_PERIP_CLK_CFG, SPEAR1310_CLCD_CLK_SHIFT,
                        SPEAR1310_CLCD_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "clcd_pixel_clk", NULL);
+       clk_register_clkdev(clk, "clcd_pixel_mclk", NULL);
 
        clk = clk_register_gate(NULL, "clcd_clk", "clcd_pixel_mclk", 0,
                        SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_CLCD_CLK_ENB, 0,
                        &_lock);
-       clk_register_clkdev(clk, "clcd_clk", NULL);
+       clk_register_clkdev(clk, NULL, "e1000000.clcd");
 
        /* i2s */
        clk = clk_register_mux(NULL, "i2s_src_mclk", i2s_src_parents,
                        ARRAY_SIZE(i2s_src_parents), 0, SPEAR1310_I2S_CLK_CFG,
                        SPEAR1310_I2S_SRC_CLK_SHIFT, SPEAR1310_I2S_SRC_CLK_MASK,
                        0, &_lock);
-       clk_register_clkdev(clk, "i2s_src_clk", NULL);
+       clk_register_clkdev(clk, "i2s_src_mclk", NULL);
 
        clk = clk_register_aux("i2s_prs1_clk", NULL, "i2s_src_mclk", 0,
                        SPEAR1310_I2S_CLK_CFG, &i2s_prs1_masks, i2s_prs1_rtbl,
@@ -653,10 +669,10 @@ void __init spear1310_clk_init(void)
        clk_register_clkdev(clk, "i2s_prs1_clk", NULL);
 
        clk = clk_register_mux(NULL, "i2s_ref_mclk", i2s_ref_parents,
-                       ARRAY_SIZE(i2s_ref_parents), 0, SPEAR1310_I2S_CLK_CFG,
-                       SPEAR1310_I2S_REF_SHIFT, SPEAR1310_I2S_REF_SEL_MASK, 0,
-                       &_lock);
-       clk_register_clkdev(clk, "i2s_ref_clk", NULL);
+                       ARRAY_SIZE(i2s_ref_parents), CLK_SET_RATE_PARENT,
+                       SPEAR1310_I2S_CLK_CFG, SPEAR1310_I2S_REF_SHIFT,
+                       SPEAR1310_I2S_REF_SEL_MASK, 0, &_lock);
+       clk_register_clkdev(clk, "i2s_ref_mclk", NULL);
 
        clk = clk_register_gate(NULL, "i2s_ref_pad_clk", "i2s_ref_mclk", 0,
                        SPEAR1310_PERIP2_CLK_ENB, SPEAR1310_I2S_REF_PAD_CLK_ENB,
@@ -664,7 +680,7 @@ void __init spear1310_clk_init(void)
        clk_register_clkdev(clk, "i2s_ref_pad_clk", NULL);
 
        clk = clk_register_aux("i2s_sclk_clk", "i2s_sclk_gclk",
-                       "i2s_ref_pad_clk", 0, SPEAR1310_I2S_CLK_CFG,
+                       "i2s_ref_mclk", 0, SPEAR1310_I2S_CLK_CFG,
                        &i2s_sclk_masks, i2s_sclk_rtbl,
                        ARRAY_SIZE(i2s_sclk_rtbl), &_lock, &clk1);
        clk_register_clkdev(clk, "i2s_sclk_clk", NULL);
@@ -705,35 +721,37 @@ void __init spear1310_clk_init(void)
        clk = clk_register_gate(NULL, "usbh0_clk", "ahb_clk", 0,
                        SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_UHC0_CLK_ENB, 0,
                        &_lock);
-       clk_register_clkdev(clk, "usbh.0_clk", NULL);
+       clk_register_clkdev(clk, NULL, "e4000000.ohci");
+       clk_register_clkdev(clk, NULL, "e4800000.ehci");
 
        clk = clk_register_gate(NULL, "usbh1_clk", "ahb_clk", 0,
                        SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_UHC1_CLK_ENB, 0,
                        &_lock);
-       clk_register_clkdev(clk, "usbh.1_clk", NULL);
+       clk_register_clkdev(clk, NULL, "e5000000.ohci");
+       clk_register_clkdev(clk, NULL, "e5800000.ehci");
 
        clk = clk_register_gate(NULL, "uoc_clk", "ahb_clk", 0,
                        SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_UOC_CLK_ENB, 0,
                        &_lock);
-       clk_register_clkdev(clk, NULL, "uoc");
+       clk_register_clkdev(clk, NULL, "e3800000.otg");
 
        clk = clk_register_gate(NULL, "pcie_sata_0_clk", "ahb_clk", 0,
                        SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_PCIE_SATA_0_CLK_ENB,
                        0, &_lock);
        clk_register_clkdev(clk, NULL, "dw_pcie.0");
-       clk_register_clkdev(clk, NULL, "ahci.0");
+       clk_register_clkdev(clk, NULL, "b1000000.ahci");
 
        clk = clk_register_gate(NULL, "pcie_sata_1_clk", "ahb_clk", 0,
                        SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_PCIE_SATA_1_CLK_ENB,
                        0, &_lock);
        clk_register_clkdev(clk, NULL, "dw_pcie.1");
-       clk_register_clkdev(clk, NULL, "ahci.1");
+       clk_register_clkdev(clk, NULL, "b1800000.ahci");
 
        clk = clk_register_gate(NULL, "pcie_sata_2_clk", "ahb_clk", 0,
                        SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_PCIE_SATA_2_CLK_ENB,
                        0, &_lock);
        clk_register_clkdev(clk, NULL, "dw_pcie.2");
-       clk_register_clkdev(clk, NULL, "ahci.2");
+       clk_register_clkdev(clk, NULL, "b4000000.ahci");
 
        clk = clk_register_gate(NULL, "sysram0_clk", "ahb_clk", 0,
                        SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_SYSRAM0_CLK_ENB, 0,
@@ -751,10 +769,10 @@ void __init spear1310_clk_init(void)
        clk_register_clkdev(clk, "adc_syn_clk", NULL);
        clk_register_clkdev(clk1, "adc_syn_gclk", NULL);
 
-       clk = clk_register_gate(NULL, "adc_clk", "adc_syn_gclk", 0,
-                       SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_ADC_CLK_ENB, 0,
-                       &_lock);
-       clk_register_clkdev(clk, NULL, "adc_clk");
+       clk = clk_register_gate(NULL, "adc_clk", "adc_syn_gclk",
+                       CLK_SET_RATE_PARENT, SPEAR1310_PERIP1_CLK_ENB,
+                       SPEAR1310_ADC_CLK_ENB, 0, &_lock);
+       clk_register_clkdev(clk, NULL, "e0080000.adc");
 
        /* clock derived from apb clk */
        clk = clk_register_gate(NULL, "ssp0_clk", "apb_clk", 0,
@@ -916,15 +934,15 @@ void __init spear1310_clk_init(void)
                        SPEAR1310_RAS_CTRL_REG1,
                        SPEAR1310_SMII_RGMII_PHY_CLK_SHIFT,
                        SPEAR1310_PHY_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, NULL, "stmmacphy.1");
-       clk_register_clkdev(clk, NULL, "stmmacphy.2");
-       clk_register_clkdev(clk, NULL, "stmmacphy.4");
+       clk_register_clkdev(clk, "stmmacphy.1", NULL);
+       clk_register_clkdev(clk, "stmmacphy.2", NULL);
+       clk_register_clkdev(clk, "stmmacphy.4", NULL);
 
        clk = clk_register_mux(NULL, "rmii_phy_mclk", rmii_phy_parents,
                        ARRAY_SIZE(rmii_phy_parents), 0,
                        SPEAR1310_RAS_CTRL_REG1, SPEAR1310_RMII_PHY_CLK_SHIFT,
                        SPEAR1310_PHY_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, NULL, "stmmacphy.3");
+       clk_register_clkdev(clk, "stmmacphy.3", NULL);
 
        clk = clk_register_mux(NULL, "uart1_mclk", uart_parents,
                        ARRAY_SIZE(uart_parents), 0, SPEAR1310_RAS_CTRL_REG0,
index 2352cee..82abea3 100644 (file)
@@ -190,6 +190,7 @@ static struct pll_rate_tbl pll4_rtbl[] = {
  * different values of vco1div2
  */
 static struct frac_rate_tbl amba_synth_rtbl[] = {
+       {.div = 0x073A8}, /* for vco1div2 = 600 MHz */
        {.div = 0x06062}, /* for vco1div2 = 500 MHz */
        {.div = 0x04D1B}, /* for vco1div2 = 400 MHz */
        {.div = 0x04000}, /* for vco1div2 = 332 MHz */
@@ -220,6 +221,12 @@ static struct frac_rate_tbl amba_synth_rtbl[] = {
  * 500                 400             200                     0x02800
  * 500                 500             250                     0x02000
  * --------------------------------------------------------------------
+ * 600                 200             100                     0x06000
+ * 600                 250             125                     0x04CCE
+ * 600                 332             166                     0x039D5
+ * 600                 400             200                     0x03000
+ * 600                 500             250                     0x02666
+ * --------------------------------------------------------------------
  * 664                 200             100                     0x06a38
  * 664                 250             125                     0x054FD
  * 664                 332             166                     0x04000
@@ -238,28 +245,50 @@ static struct frac_rate_tbl sys_synth_rtbl[] = {
        {.div = 0x08000},
        {.div = 0x06a38},
        {.div = 0x06666},
+       {.div = 0x06000},
        {.div = 0x054FD},
        {.div = 0x05000},
        {.div = 0x04D18},
+       {.div = 0x04CCE},
        {.div = 0x04000},
+       {.div = 0x039D5},
        {.div = 0x0351E},
        {.div = 0x03333},
        {.div = 0x03031},
+       {.div = 0x03000},
        {.div = 0x02A7E},
        {.div = 0x02800},
        {.div = 0x0268D},
+       {.div = 0x02666},
        {.div = 0x02000},
 };
 
 /* aux rate configuration table, in ascending order of rates */
 static struct aux_rate_tbl aux_rtbl[] = {
-       /* For VCO1div2 = 500 MHz */
-       {.xscale = 10, .yscale = 204, .eq = 0}, /* 12.29 MHz */
-       {.xscale = 4, .yscale = 21, .eq = 0}, /* 48 MHz */
-       {.xscale = 2, .yscale = 6, .eq = 0}, /* 83 MHz */
-       {.xscale = 2, .yscale = 4, .eq = 0}, /* 125 MHz */
-       {.xscale = 1, .yscale = 3, .eq = 1}, /* 166 MHz */
-       {.xscale = 1, .yscale = 2, .eq = 1}, /* 250 MHz */
+       /* 12.29MHz for vic1div2=600MHz and 10.24MHz for VCO1div2=500MHz */
+       {.xscale = 5, .yscale = 122, .eq = 0},
+       /* 14.70MHz for vic1div2=600MHz and 12.29MHz for VCO1div2=500MHz */
+       {.xscale = 10, .yscale = 204, .eq = 0},
+       /* 48MHz for vic1div2=600MHz and 40 MHz for VCO1div2=500MHz */
+       {.xscale = 4, .yscale = 25, .eq = 0},
+       /* 57.14MHz for vic1div2=600MHz and 48 MHz for VCO1div2=500MHz */
+       {.xscale = 4, .yscale = 21, .eq = 0},
+       /* 83.33MHz for vic1div2=600MHz and 69.44MHz for VCO1div2=500MHz */
+       {.xscale = 5, .yscale = 18, .eq = 0},
+       /* 100MHz for vic1div2=600MHz and 83.33 MHz for VCO1div2=500MHz */
+       {.xscale = 2, .yscale = 6, .eq = 0},
+       /* 125MHz for vic1div2=600MHz and 104.1MHz for VCO1div2=500MHz */
+       {.xscale = 5, .yscale = 12, .eq = 0},
+       /* 150MHz for vic1div2=600MHz and 125MHz for VCO1div2=500MHz */
+       {.xscale = 2, .yscale = 4, .eq = 0},
+       /* 166MHz for vic1div2=600MHz and 138.88MHz for VCO1div2=500MHz */
+       {.xscale = 5, .yscale = 18, .eq = 1},
+       /* 200MHz for vic1div2=600MHz and 166MHz for VCO1div2=500MHz */
+       {.xscale = 1, .yscale = 3, .eq = 1},
+       /* 250MHz for vic1div2=600MHz and 208.33MHz for VCO1div2=500MHz */
+       {.xscale = 5, .yscale = 12, .eq = 1},
+       /* 300MHz for vic1div2=600MHz and 250MHz for VCO1div2=500MHz */
+       {.xscale = 1, .yscale = 2, .eq = 1},
 };
 
 /* gmac rate configuration table, in ascending order of rates */
@@ -273,16 +302,23 @@ static struct aux_rate_tbl gmac_rtbl[] = {
 
 /* clcd rate configuration table, in ascending order of rates */
 static struct frac_rate_tbl clcd_rtbl[] = {
+       {.div = 0x18000}, /* 25 Mhz , for vc01div4 = 300 MHz*/
+       {.div = 0x1638E}, /* 27 Mhz , for vc01div4 = 300 MHz*/
        {.div = 0x14000}, /* 25 Mhz , for vc01div4 = 250 MHz*/
        {.div = 0x1284B}, /* 27 Mhz , for vc01div4 = 250 MHz*/
        {.div = 0x0D8D3}, /* 58 Mhz , for vco1div4 = 393 MHz */
        {.div = 0x0B72C}, /* 58 Mhz , for vco1div4 = 332 MHz */
+       {.div = 0x0A584}, /* 58 Mhz , for vco1div4 = 300 MHz */
+       {.div = 0x093B1}, /* 65 Mhz , for vc01div4 = 300 MHz*/
        {.div = 0x089EE}, /* 58 Mhz , for vc01div4 = 250 MHz*/
+       {.div = 0x081BA}, /* 74 Mhz , for vc01div4 = 300 MHz*/
        {.div = 0x07BA0}, /* 65 Mhz , for vc01div4 = 250 MHz*/
        {.div = 0x06f1C}, /* 72 Mhz , for vc01div4 = 250 MHz*/
        {.div = 0x06E58}, /* 58 Mhz , for vco1div4 = 200 MHz */
        {.div = 0x06c1B}, /* 74 Mhz , for vc01div4 = 250 MHz*/
+       {.div = 0x058E3}, /* 108 Mhz , for vc01div4 = 300 MHz*/
        {.div = 0x04A12}, /* 108 Mhz , for vc01div4 = 250 MHz*/
+       {.div = 0x040A5}, /* 148.5 Mhz , for vc01div4 = 300 MHz*/
        {.div = 0x0378E}, /* 144 Mhz , for vc01div4 = 250 MHz*/
        {.div = 0x0360D}, /* 148 Mhz , for vc01div4 = 250 MHz*/
        {.div = 0x035E0}, /* 148.5 MHz, for vc01div4 = 250 MHz*/
@@ -351,26 +387,37 @@ static struct aux_rate_tbl adc_rtbl[] = {
 
 /* General synth rate configuration table, in ascending order of rates */
 static struct frac_rate_tbl gen_rtbl[] = {
-       /* For vco1div4 = 250 MHz */
-       {.div = 0x1624E}, /* 22.5792 MHz */
-       {.div = 0x14585}, /* 24.576 MHz */
-       {.div = 0x14000}, /* 25 MHz */
-       {.div = 0x0B127}, /* 45.1584 MHz */
-       {.div = 0x0A000}, /* 50 MHz */
-       {.div = 0x061A8}, /* 81.92 MHz */
-       {.div = 0x05000}, /* 100 MHz */
-       {.div = 0x02800}, /* 200 MHz */
-       {.div = 0x02620}, /* 210 MHz */
-       {.div = 0x02460}, /* 220 MHz */
-       {.div = 0x022C0}, /* 230 MHz */
-       {.div = 0x02160}, /* 240 MHz */
-       {.div = 0x02000}, /* 250 MHz */
+       {.div = 0x1A92B}, /* 22.5792 MHz for vco1div4=300 MHz*/
+       {.div = 0x186A0}, /* 24.576 MHz for vco1div4=300 MHz*/
+       {.div = 0x18000}, /* 25 MHz for vco1div4=300 MHz*/
+       {.div = 0x1624E}, /* 22.5792 MHz for vco1div4=250 MHz*/
+       {.div = 0x14585}, /* 24.576 MHz for vco1div4=250 MHz*/
+       {.div = 0x14000}, /* 25 MHz for vco1div4=250 MHz*/
+       {.div = 0x0D495}, /* 45.1584 MHz for vco1div4=300 MHz*/
+       {.div = 0x0C000}, /* 50 MHz for vco1div4=300 MHz*/
+       {.div = 0x0B127}, /* 45.1584 MHz for vco1div4=250 MHz*/
+       {.div = 0x0A000}, /* 50 MHz for vco1div4=250 MHz*/
+       {.div = 0x07530}, /* 81.92 MHz for vco1div4=300 MHz*/
+       {.div = 0x061A8}, /* 81.92 MHz for vco1div4=250 MHz*/
+       {.div = 0x06000}, /* 100 MHz for vco1div4=300 MHz*/
+       {.div = 0x05000}, /* 100 MHz for vco1div4=250 MHz*/
+       {.div = 0x03000}, /* 200 MHz for vco1div4=300 MHz*/
+       {.div = 0x02DB6}, /* 210 MHz for vco1div4=300 MHz*/
+       {.div = 0x02BA2}, /* 220 MHz for vco1div4=300 MHz*/
+       {.div = 0x029BD}, /* 230 MHz for vco1div4=300 MHz*/
+       {.div = 0x02800}, /* 200 MHz for vco1div4=250 MHz*/
+       {.div = 0x02666}, /* 250 MHz for vco1div4=300 MHz*/
+       {.div = 0x02620}, /* 210 MHz for vco1div4=250 MHz*/
+       {.div = 0x02460}, /* 220 MHz for vco1div4=250 MHz*/
+       {.div = 0x022C0}, /* 230 MHz for vco1div4=250 MHz*/
+       {.div = 0x02160}, /* 240 MHz for vco1div4=250 MHz*/
+       {.div = 0x02000}, /* 250 MHz for vco1div4=250 MHz*/
 };
 
 /* clock parents */
 static const char *vco_parents[] = { "osc_24m_clk", "osc_25m_clk", };
 static const char *sys_parents[] = { "pll1_clk", "pll1_clk", "pll1_clk",
-       "pll1_clk", "sys_synth_clk", "sys_synth_clk", "pll2_clk", "pll3_clk", };
+       "pll1_clk", "sys_syn_clk", "sys_syn_clk", "pll2_clk", "pll3_clk", };
 static const char *ahb_parents[] = { "cpu_div3_clk", "amba_syn_clk", };
 static const char *gpt_parents[] = { "osc_24m_clk", "apb_clk", };
 static const char *uart0_parents[] = { "pll5_clk", "osc_24m_clk",
@@ -391,16 +438,13 @@ static const char *spdif_in_parents[] = { "pll2_clk", "gen_syn3_clk", };
 
 static const char *gen_synth0_1_parents[] = { "vco1div4_clk", "vco3div2_clk",
        "pll3_clk", };
-static const char *gen_synth2_3_parents[] = { "vco1div4_clk", "vco3div2_clk",
+static const char *gen_synth2_3_parents[] = { "vco1div4_clk", "vco2div2_clk",
        "pll2_clk", };
 
 void __init spear1340_clk_init(void)
 {
        struct clk *clk, *clk1;
 
-       clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
-       clk_register_clkdev(clk, "apb_pclk", NULL);
-
        clk = clk_register_fixed_rate(NULL, "osc_32k_clk", NULL, CLK_IS_ROOT,
                        32000);
        clk_register_clkdev(clk, "osc_32k_clk", NULL);
@@ -425,7 +469,7 @@ void __init spear1340_clk_init(void)
        clk = clk_register_gate(NULL, "rtc-spear", "osc_32k_clk", 0,
                        SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_RTC_CLK_ENB, 0,
                        &_lock);
-       clk_register_clkdev(clk, NULL, "fc900000.rtc");
+       clk_register_clkdev(clk, NULL, "e0580000.rtc");
 
        /* clock derived from 24 or 25 MHz osc clk */
        /* vco-pll */
@@ -499,7 +543,7 @@ void __init spear1340_clk_init(void)
        clk = clk_register_gate(NULL, "thermal_gclk", "thermal_clk", 0,
                        SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_THSENS_CLK_ENB, 0,
                        &_lock);
-       clk_register_clkdev(clk, NULL, "spear_thermal");
+       clk_register_clkdev(clk, NULL, "e07008c4.thermal");
 
        /* clock derived from pll4 clk */
        clk = clk_register_fixed_factor(NULL, "ddr_clk", "pll4_clk", 0, 1,
@@ -521,7 +565,7 @@ void __init spear1340_clk_init(void)
                        ARRAY_SIZE(sys_parents), 0, SPEAR1340_SYS_CLK_CTRL,
                        SPEAR1340_SCLK_SRC_SEL_SHIFT,
                        SPEAR1340_SCLK_SRC_SEL_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "sys_clk", NULL);
+       clk_register_clkdev(clk, "sys_mclk", NULL);
 
        clk = clk_register_fixed_factor(NULL, "cpu_clk", "sys_mclk", 0, 1,
                        2);
@@ -535,6 +579,10 @@ void __init spear1340_clk_init(void)
                        2);
        clk_register_clkdev(clk, NULL, "ec800620.wdt");
 
+       clk = clk_register_fixed_factor(NULL, "smp_twd_clk", "cpu_clk", 0, 1,
+                       2);
+       clk_register_clkdev(clk, NULL, "smp_twd");
+
        clk = clk_register_mux(NULL, "ahb_clk", ahb_parents,
                        ARRAY_SIZE(ahb_parents), 0, SPEAR1340_SYS_CLK_CTRL,
                        SPEAR1340_HCLK_SRC_SEL_SHIFT,
@@ -594,14 +642,14 @@ void __init spear1340_clk_init(void)
        clk_register_clkdev(clk1, "uart0_syn_gclk", NULL);
 
        clk = clk_register_mux(NULL, "uart0_mclk", uart0_parents,
-                       ARRAY_SIZE(uart0_parents), 0, SPEAR1340_PERIP_CLK_CFG,
-                       SPEAR1340_UART0_CLK_SHIFT, SPEAR1340_UART_CLK_MASK, 0,
-                       &_lock);
+                       ARRAY_SIZE(uart0_parents), CLK_SET_RATE_PARENT,
+                       SPEAR1340_PERIP_CLK_CFG, SPEAR1340_UART0_CLK_SHIFT,
+                       SPEAR1340_UART_CLK_MASK, 0, &_lock);
        clk_register_clkdev(clk, "uart0_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "uart0_clk", "uart0_mclk", 0,
-                       SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_UART0_CLK_ENB, 0,
-                       &_lock);
+       clk = clk_register_gate(NULL, "uart0_clk", "uart0_mclk",
+                       CLK_SET_RATE_PARENT, SPEAR1340_PERIP1_CLK_ENB,
+                       SPEAR1340_UART0_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, NULL, "e0000000.serial");
 
        clk = clk_register_aux("uart1_syn_clk", "uart1_syn_gclk",
@@ -627,9 +675,9 @@ void __init spear1340_clk_init(void)
        clk_register_clkdev(clk, "sdhci_syn_clk", NULL);
        clk_register_clkdev(clk1, "sdhci_syn_gclk", NULL);
 
-       clk = clk_register_gate(NULL, "sdhci_clk", "sdhci_syn_gclk", 0,
-                       SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_SDHCI_CLK_ENB, 0,
-                       &_lock);
+       clk = clk_register_gate(NULL, "sdhci_clk", "sdhci_syn_gclk",
+                       CLK_SET_RATE_PARENT, SPEAR1340_PERIP1_CLK_ENB,
+                       SPEAR1340_SDHCI_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, NULL, "b3000000.sdhci");
 
        clk = clk_register_aux("cfxd_syn_clk", "cfxd_syn_gclk", "vco1div2_clk",
@@ -638,9 +686,9 @@ void __init spear1340_clk_init(void)
        clk_register_clkdev(clk, "cfxd_syn_clk", NULL);
        clk_register_clkdev(clk1, "cfxd_syn_gclk", NULL);
 
-       clk = clk_register_gate(NULL, "cfxd_clk", "cfxd_syn_gclk", 0,
-                       SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_CFXD_CLK_ENB, 0,
-                       &_lock);
+       clk = clk_register_gate(NULL, "cfxd_clk", "cfxd_syn_gclk",
+                       CLK_SET_RATE_PARENT, SPEAR1340_PERIP1_CLK_ENB,
+                       SPEAR1340_CFXD_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, NULL, "b2800000.cf");
        clk_register_clkdev(clk, NULL, "arasan_xd");
 
@@ -651,15 +699,15 @@ void __init spear1340_clk_init(void)
        clk_register_clkdev(clk1, "c3_syn_gclk", NULL);
 
        clk = clk_register_mux(NULL, "c3_mclk", c3_parents,
-                       ARRAY_SIZE(c3_parents), 0, SPEAR1340_PERIP_CLK_CFG,
-                       SPEAR1340_C3_CLK_SHIFT, SPEAR1340_C3_CLK_MASK, 0,
-                       &_lock);
+                       ARRAY_SIZE(c3_parents), CLK_SET_RATE_PARENT,
+                       SPEAR1340_PERIP_CLK_CFG, SPEAR1340_C3_CLK_SHIFT,
+                       SPEAR1340_C3_CLK_MASK, 0, &_lock);
        clk_register_clkdev(clk, "c3_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "c3_clk", "c3_mclk", 0,
+       clk = clk_register_gate(NULL, "c3_clk", "c3_mclk", CLK_SET_RATE_PARENT,
                        SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_C3_CLK_ENB, 0,
                        &_lock);
-       clk_register_clkdev(clk, NULL, "c3");
+       clk_register_clkdev(clk, NULL, "e1800000.c3");
 
        /* gmac */
        clk = clk_register_mux(NULL, "phy_input_mclk", gmac_phy_input_parents,
@@ -679,7 +727,7 @@ void __init spear1340_clk_init(void)
                        ARRAY_SIZE(gmac_phy_parents), 0,
                        SPEAR1340_PERIP_CLK_CFG, SPEAR1340_GMAC_PHY_CLK_SHIFT,
                        SPEAR1340_GMAC_PHY_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, NULL, "stmmacphy.0");
+       clk_register_clkdev(clk, "stmmacphy.0", NULL);
 
        /* clcd */
        clk = clk_register_mux(NULL, "clcd_syn_mclk", clcd_synth_parents,
@@ -694,33 +742,34 @@ void __init spear1340_clk_init(void)
        clk_register_clkdev(clk, "clcd_syn_clk", NULL);
 
        clk = clk_register_mux(NULL, "clcd_pixel_mclk", clcd_pixel_parents,
-                       ARRAY_SIZE(clcd_pixel_parents), 0,
+                       ARRAY_SIZE(clcd_pixel_parents), CLK_SET_RATE_PARENT,
                        SPEAR1340_PERIP_CLK_CFG, SPEAR1340_CLCD_CLK_SHIFT,
                        SPEAR1340_CLCD_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "clcd_pixel_clk", NULL);
+       clk_register_clkdev(clk, "clcd_pixel_mclk", NULL);
 
        clk = clk_register_gate(NULL, "clcd_clk", "clcd_pixel_mclk", 0,
                        SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_CLCD_CLK_ENB, 0,
                        &_lock);
-       clk_register_clkdev(clk, "clcd_clk", NULL);
+       clk_register_clkdev(clk, NULL, "e1000000.clcd");
 
        /* i2s */
        clk = clk_register_mux(NULL, "i2s_src_mclk", i2s_src_parents,
                        ARRAY_SIZE(i2s_src_parents), 0, SPEAR1340_I2S_CLK_CFG,
                        SPEAR1340_I2S_SRC_CLK_SHIFT, SPEAR1340_I2S_SRC_CLK_MASK,
                        0, &_lock);
-       clk_register_clkdev(clk, "i2s_src_clk", NULL);
+       clk_register_clkdev(clk, "i2s_src_mclk", NULL);
 
-       clk = clk_register_aux("i2s_prs1_clk", NULL, "i2s_src_mclk", 0,
-                       SPEAR1340_I2S_CLK_CFG, &i2s_prs1_masks, i2s_prs1_rtbl,
+       clk = clk_register_aux("i2s_prs1_clk", NULL, "i2s_src_mclk",
+                       CLK_SET_RATE_PARENT, SPEAR1340_I2S_CLK_CFG,
+                       &i2s_prs1_masks, i2s_prs1_rtbl,
                        ARRAY_SIZE(i2s_prs1_rtbl), &_lock, NULL);
        clk_register_clkdev(clk, "i2s_prs1_clk", NULL);
 
        clk = clk_register_mux(NULL, "i2s_ref_mclk", i2s_ref_parents,
-                       ARRAY_SIZE(i2s_ref_parents), 0, SPEAR1340_I2S_CLK_CFG,
-                       SPEAR1340_I2S_REF_SHIFT, SPEAR1340_I2S_REF_SEL_MASK, 0,
-                       &_lock);
-       clk_register_clkdev(clk, "i2s_ref_clk", NULL);
+                       ARRAY_SIZE(i2s_ref_parents), CLK_SET_RATE_PARENT,
+                       SPEAR1340_I2S_CLK_CFG, SPEAR1340_I2S_REF_SHIFT,
+                       SPEAR1340_I2S_REF_SEL_MASK, 0, &_lock);
+       clk_register_clkdev(clk, "i2s_ref_mclk", NULL);
 
        clk = clk_register_gate(NULL, "i2s_ref_pad_clk", "i2s_ref_mclk", 0,
                        SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_I2S_REF_PAD_CLK_ENB,
@@ -769,23 +818,25 @@ void __init spear1340_clk_init(void)
        clk = clk_register_gate(NULL, "usbh0_clk", "ahb_clk", 0,
                        SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_UHC0_CLK_ENB, 0,
                        &_lock);
-       clk_register_clkdev(clk, "usbh.0_clk", NULL);
+       clk_register_clkdev(clk, NULL, "e4000000.ohci");
+       clk_register_clkdev(clk, NULL, "e4800000.ehci");
 
        clk = clk_register_gate(NULL, "usbh1_clk", "ahb_clk", 0,
                        SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_UHC1_CLK_ENB, 0,
                        &_lock);
-       clk_register_clkdev(clk, "usbh.1_clk", NULL);
+       clk_register_clkdev(clk, NULL, "e5000000.ohci");
+       clk_register_clkdev(clk, NULL, "e5800000.ehci");
 
        clk = clk_register_gate(NULL, "uoc_clk", "ahb_clk", 0,
                        SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_UOC_CLK_ENB, 0,
                        &_lock);
-       clk_register_clkdev(clk, NULL, "uoc");
+       clk_register_clkdev(clk, NULL, "e3800000.otg");
 
        clk = clk_register_gate(NULL, "pcie_sata_clk", "ahb_clk", 0,
                        SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_PCIE_SATA_CLK_ENB,
                        0, &_lock);
        clk_register_clkdev(clk, NULL, "dw_pcie");
-       clk_register_clkdev(clk, NULL, "ahci");
+       clk_register_clkdev(clk, NULL, "b1000000.ahci");
 
        clk = clk_register_gate(NULL, "sysram0_clk", "ahb_clk", 0,
                        SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_SYSRAM0_CLK_ENB, 0,
@@ -803,10 +854,10 @@ void __init spear1340_clk_init(void)
        clk_register_clkdev(clk, "adc_syn_clk", NULL);
        clk_register_clkdev(clk1, "adc_syn_gclk", NULL);
 
-       clk = clk_register_gate(NULL, "adc_clk", "adc_syn_gclk", 0,
-                       SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_ADC_CLK_ENB, 0,
-                       &_lock);
-       clk_register_clkdev(clk, NULL, "adc_clk");
+       clk = clk_register_gate(NULL, "adc_clk", "adc_syn_gclk",
+                       CLK_SET_RATE_PARENT, SPEAR1340_PERIP1_CLK_ENB,
+                       SPEAR1340_ADC_CLK_ENB, 0, &_lock);
+       clk_register_clkdev(clk, NULL, "e0080000.adc");
 
        /* clock derived from apb clk */
        clk = clk_register_gate(NULL, "ssp_clk", "apb_clk", 0,
@@ -827,12 +878,12 @@ void __init spear1340_clk_init(void)
        clk = clk_register_gate(NULL, "i2s_play_clk", "apb_clk", 0,
                        SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_I2S_PLAY_CLK_ENB, 0,
                        &_lock);
-       clk_register_clkdev(clk, NULL, "b2400000.i2s");
+       clk_register_clkdev(clk, NULL, "b2400000.i2s-play");
 
        clk = clk_register_gate(NULL, "i2s_rec_clk", "apb_clk", 0,
                        SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_I2S_REC_CLK_ENB, 0,
                        &_lock);
-       clk_register_clkdev(clk, NULL, "b2000000.i2s");
+       clk_register_clkdev(clk, NULL, "b2000000.i2s-rec");
 
        clk = clk_register_gate(NULL, "kbd_clk", "apb_clk", 0,
                        SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_KBD_CLK_ENB, 0,
@@ -844,37 +895,37 @@ void __init spear1340_clk_init(void)
                        ARRAY_SIZE(gen_synth0_1_parents), 0, SPEAR1340_PLL_CFG,
                        SPEAR1340_GEN_SYNT0_1_CLK_SHIFT,
                        SPEAR1340_GEN_SYNT_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "gen_syn0_1_clk", NULL);
+       clk_register_clkdev(clk, "gen_syn0_1_mclk", NULL);
 
        clk = clk_register_mux(NULL, "gen_syn2_3_mclk", gen_synth2_3_parents,
                        ARRAY_SIZE(gen_synth2_3_parents), 0, SPEAR1340_PLL_CFG,
                        SPEAR1340_GEN_SYNT2_3_CLK_SHIFT,
                        SPEAR1340_GEN_SYNT_CLK_MASK, 0, &_lock);
-       clk_register_clkdev(clk, "gen_syn2_3_clk", NULL);
+       clk_register_clkdev(clk, "gen_syn2_3_mclk", NULL);
 
-       clk = clk_register_frac("gen_syn0_clk", "gen_syn0_1_clk", 0,
+       clk = clk_register_frac("gen_syn0_clk", "gen_syn0_1_mclk", 0,
                        SPEAR1340_GEN_CLK_SYNT0, gen_rtbl, ARRAY_SIZE(gen_rtbl),
                        &_lock);
        clk_register_clkdev(clk, "gen_syn0_clk", NULL);
 
-       clk = clk_register_frac("gen_syn1_clk", "gen_syn0_1_clk", 0,
+       clk = clk_register_frac("gen_syn1_clk", "gen_syn0_1_mclk", 0,
                        SPEAR1340_GEN_CLK_SYNT1, gen_rtbl, ARRAY_SIZE(gen_rtbl),
                        &_lock);
        clk_register_clkdev(clk, "gen_syn1_clk", NULL);
 
-       clk = clk_register_frac("gen_syn2_clk", "gen_syn2_3_clk", 0,
+       clk = clk_register_frac("gen_syn2_clk", "gen_syn2_3_mclk", 0,
                        SPEAR1340_GEN_CLK_SYNT2, gen_rtbl, ARRAY_SIZE(gen_rtbl),
                        &_lock);
        clk_register_clkdev(clk, "gen_syn2_clk", NULL);
 
-       clk = clk_register_frac("gen_syn3_clk", "gen_syn2_3_clk", 0,
+       clk = clk_register_frac("gen_syn3_clk", "gen_syn2_3_mclk", 0,
                        SPEAR1340_GEN_CLK_SYNT3, gen_rtbl, ARRAY_SIZE(gen_rtbl),
                        &_lock);
        clk_register_clkdev(clk, "gen_syn3_clk", NULL);
 
-       clk = clk_register_gate(NULL, "mali_clk", "gen_syn3_clk", 0,
-                       SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_MALI_CLK_ENB, 0,
-                       &_lock);
+       clk = clk_register_gate(NULL, "mali_clk", "gen_syn3_clk",
+                       CLK_SET_RATE_PARENT, SPEAR1340_PERIP3_CLK_ENB,
+                       SPEAR1340_MALI_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, NULL, "mali");
 
        clk = clk_register_gate(NULL, "cec0_clk", "ahb_clk", 0,
@@ -888,26 +939,26 @@ void __init spear1340_clk_init(void)
        clk_register_clkdev(clk, NULL, "spear_cec.1");
 
        clk = clk_register_mux(NULL, "spdif_out_mclk", spdif_out_parents,
-                       ARRAY_SIZE(spdif_out_parents), 0,
+                       ARRAY_SIZE(spdif_out_parents), CLK_SET_RATE_PARENT,
                        SPEAR1340_PERIP_CLK_CFG, SPEAR1340_SPDIF_OUT_CLK_SHIFT,
                        SPEAR1340_SPDIF_CLK_MASK, 0, &_lock);
        clk_register_clkdev(clk, "spdif_out_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "spdif_out_clk", "spdif_out_mclk", 0,
-                       SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_SPDIF_OUT_CLK_ENB,
-                       0, &_lock);
-       clk_register_clkdev(clk, NULL, "spdif-out");
+       clk = clk_register_gate(NULL, "spdif_out_clk", "spdif_out_mclk",
+                       CLK_SET_RATE_PARENT, SPEAR1340_PERIP3_CLK_ENB,
+                       SPEAR1340_SPDIF_OUT_CLK_ENB, 0, &_lock);
+       clk_register_clkdev(clk, NULL, "d0000000.spdif-out");
 
        clk = clk_register_mux(NULL, "spdif_in_mclk", spdif_in_parents,
-                       ARRAY_SIZE(spdif_in_parents), 0,
+                       ARRAY_SIZE(spdif_in_parents), CLK_SET_RATE_PARENT,
                        SPEAR1340_PERIP_CLK_CFG, SPEAR1340_SPDIF_IN_CLK_SHIFT,
                        SPEAR1340_SPDIF_CLK_MASK, 0, &_lock);
        clk_register_clkdev(clk, "spdif_in_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "spdif_in_clk", "spdif_in_mclk", 0,
-                       SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_SPDIF_IN_CLK_ENB, 0,
-                       &_lock);
-       clk_register_clkdev(clk, NULL, "spdif-in");
+       clk = clk_register_gate(NULL, "spdif_in_clk", "spdif_in_mclk",
+                       CLK_SET_RATE_PARENT, SPEAR1340_PERIP3_CLK_ENB,
+                       SPEAR1340_SPDIF_IN_CLK_ENB, 0, &_lock);
+       clk_register_clkdev(clk, NULL, "d0100000.spdif-in");
 
        clk = clk_register_gate(NULL, "acp_clk", "acp_mclk", 0,
                        SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_ACP_CLK_ENB, 0,
@@ -917,7 +968,7 @@ void __init spear1340_clk_init(void)
        clk = clk_register_gate(NULL, "plgpio_clk", "plgpio_mclk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_PLGPIO_CLK_ENB, 0,
                        &_lock);
-       clk_register_clkdev(clk, NULL, "plgpio");
+       clk_register_clkdev(clk, NULL, "e2800000.gpio");
 
        clk = clk_register_gate(NULL, "video_dec_clk", "video_dec_mclk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_DEC_CLK_ENB,
@@ -937,25 +988,25 @@ void __init spear1340_clk_init(void)
        clk = clk_register_gate(NULL, "cam0_clk", "cam0_mclk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM0_CLK_ENB, 0,
                        &_lock);
-       clk_register_clkdev(clk, NULL, "spear_camif.0");
+       clk_register_clkdev(clk, NULL, "d0200000.cam0");
 
        clk = clk_register_gate(NULL, "cam1_clk", "cam1_mclk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM1_CLK_ENB, 0,
                        &_lock);
-       clk_register_clkdev(clk, NULL, "spear_camif.1");
+       clk_register_clkdev(clk, NULL, "d0300000.cam1");
 
        clk = clk_register_gate(NULL, "cam2_clk", "cam2_mclk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM2_CLK_ENB, 0,
                        &_lock);
-       clk_register_clkdev(clk, NULL, "spear_camif.2");
+       clk_register_clkdev(clk, NULL, "d0400000.cam2");
 
        clk = clk_register_gate(NULL, "cam3_clk", "cam3_mclk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM3_CLK_ENB, 0,
                        &_lock);
-       clk_register_clkdev(clk, NULL, "spear_camif.3");
+       clk_register_clkdev(clk, NULL, "d0500000.cam3");
 
-       clk = clk_register_gate(NULL, "pwm_clk", "pwm_mclk", 0,
+       clk = clk_register_gate(NULL, "pwm_clk", "ahb_clk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_PWM_CLK_ENB, 0,
                        &_lock);
-       clk_register_clkdev(clk, NULL, "pwm");
+       clk_register_clkdev(clk, NULL, "e0180000.pwm");
 }
index c315745..33d3ac5 100644 (file)
@@ -107,6 +107,12 @@ static struct pll_rate_tbl pll_rtbl[] = {
 /* aux rate configuration table, in ascending order of rates */
 static struct aux_rate_tbl aux_rtbl[] = {
        /* For PLL1 = 332 MHz */
+       {.xscale = 1, .yscale = 81, .eq = 0}, /* 2.049 MHz */
+       {.xscale = 1, .yscale = 59, .eq = 0}, /* 2.822 MHz */
+       {.xscale = 2, .yscale = 81, .eq = 0}, /* 4.098 MHz */
+       {.xscale = 3, .yscale = 89, .eq = 0}, /* 5.644 MHz */
+       {.xscale = 4, .yscale = 81, .eq = 0}, /* 8.197 MHz */
+       {.xscale = 4, .yscale = 59, .eq = 0}, /* 11.254 MHz */
        {.xscale = 2, .yscale = 27, .eq = 0}, /* 12.296 MHz */
        {.xscale = 2, .yscale = 8, .eq = 0}, /* 41.5 MHz */
        {.xscale = 2, .yscale = 4, .eq = 0}, /* 83 MHz */
@@ -157,6 +163,8 @@ static void __init spear300_clk_init(void)
                        1);
        clk_register_clkdev(clk, NULL, "a0000000.kbd");
 }
+#else
+static inline void spear300_clk_init(void) { }
 #endif
 
 /* array of all spear 310 clock lookups */
@@ -197,6 +205,8 @@ static void __init spear310_clk_init(void)
                        1);
        clk_register_clkdev(clk, NULL, "b2200000.serial");
 }
+#else
+static inline void spear310_clk_init(void) { }
 #endif
 
 /* array of all spear 320 clock lookups */
@@ -251,7 +261,7 @@ static void __init spear320_clk_init(void)
 
        clk = clk_register_fixed_factor(NULL, "pwm_clk", "ras_ahb_clk", 0, 1,
                        1);
-       clk_register_clkdev(clk, "pwm", NULL);
+       clk_register_clkdev(clk, NULL, "a8000000.pwm");
 
        clk = clk_register_fixed_factor(NULL, "ssp1_clk", "ras_ahb_clk", 0, 1,
                        1);
@@ -271,26 +281,37 @@ static void __init spear320_clk_init(void)
 
        clk = clk_register_fixed_factor(NULL, "i2s_clk", "ras_apb_clk", 0, 1,
                        1);
-       clk_register_clkdev(clk, NULL, "i2s");
+       clk_register_clkdev(clk, NULL, "a9400000.i2s");
 
        clk = clk_register_mux(NULL, "i2s_ref_clk", i2s_ref_parents,
-                       ARRAY_SIZE(i2s_ref_parents), 0, SPEAR320_CONTROL_REG,
-                       I2S_REF_PCLK_SHIFT, I2S_REF_PCLK_MASK, 0, &_lock);
+                       ARRAY_SIZE(i2s_ref_parents), CLK_SET_RATE_PARENT,
+                       SPEAR320_CONTROL_REG, I2S_REF_PCLK_SHIFT,
+                       I2S_REF_PCLK_MASK, 0, &_lock);
        clk_register_clkdev(clk, "i2s_ref_clk", NULL);
 
-       clk = clk_register_fixed_factor(NULL, "i2s_sclk", "i2s_ref_clk", 0, 1,
+       clk = clk_register_fixed_factor(NULL, "i2s_sclk", "i2s_ref_clk",
+                       CLK_SET_RATE_PARENT, 1,
                        4);
        clk_register_clkdev(clk, "i2s_sclk", NULL);
 
+       clk = clk_register_fixed_factor(NULL, "macb1_clk", "ras_apb_clk", 0, 1,
+                       1);
+       clk_register_clkdev(clk, "hclk", "aa000000.eth");
+
+       clk = clk_register_fixed_factor(NULL, "macb2_clk", "ras_apb_clk", 0, 1,
+                       1);
+       clk_register_clkdev(clk, "hclk", "ab000000.eth");
+
        clk = clk_register_mux(NULL, "rs485_clk", uartx_parents,
-                       ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG,
-                       SPEAR320_RS485_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0,
-                       &_lock);
+                       ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
+                       SPEAR320_EXT_CTRL_REG, SPEAR320_RS485_PCLK_SHIFT,
+                       SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
        clk_register_clkdev(clk, NULL, "a9300000.serial");
 
        clk = clk_register_mux(NULL, "sdhci_clk", sdhci_parents,
-                       ARRAY_SIZE(sdhci_parents), 0, SPEAR320_CONTROL_REG,
-                       SDHCI_PCLK_SHIFT, SDHCI_PCLK_MASK, 0, &_lock);
+                       ARRAY_SIZE(sdhci_parents), CLK_SET_RATE_PARENT,
+                       SPEAR320_CONTROL_REG, SDHCI_PCLK_SHIFT, SDHCI_PCLK_MASK,
+                       0, &_lock);
        clk_register_clkdev(clk, NULL, "70000000.sdhci");
 
        clk = clk_register_mux(NULL, "smii_pclk", smii0_parents,
@@ -302,49 +323,49 @@ static void __init spear320_clk_init(void)
        clk_register_clkdev(clk, NULL, "smii");
 
        clk = clk_register_mux(NULL, "uart1_clk", uartx_parents,
-                       ARRAY_SIZE(uartx_parents), 0, SPEAR320_CONTROL_REG,
-                       UART1_PCLK_SHIFT, UART1_PCLK_MASK, 0, &_lock);
+                       ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
+                       SPEAR320_CONTROL_REG, UART1_PCLK_SHIFT, UART1_PCLK_MASK,
+                       0, &_lock);
        clk_register_clkdev(clk, NULL, "a3000000.serial");
 
        clk = clk_register_mux(NULL, "uart2_clk", uartx_parents,
-                       ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG,
-                       SPEAR320_UART2_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0,
-                       &_lock);
+                       ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
+                       SPEAR320_EXT_CTRL_REG, SPEAR320_UART2_PCLK_SHIFT,
+                       SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
        clk_register_clkdev(clk, NULL, "a4000000.serial");
 
        clk = clk_register_mux(NULL, "uart3_clk", uartx_parents,
-                       ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG,
-                       SPEAR320_UART3_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0,
-                       &_lock);
+                       ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
+                       SPEAR320_EXT_CTRL_REG, SPEAR320_UART3_PCLK_SHIFT,
+                       SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
        clk_register_clkdev(clk, NULL, "a9100000.serial");
 
        clk = clk_register_mux(NULL, "uart4_clk", uartx_parents,
-                       ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG,
-                       SPEAR320_UART4_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0,
-                       &_lock);
+                       ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
+                       SPEAR320_EXT_CTRL_REG, SPEAR320_UART4_PCLK_SHIFT,
+                       SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
        clk_register_clkdev(clk, NULL, "a9200000.serial");
 
        clk = clk_register_mux(NULL, "uart5_clk", uartx_parents,
-                       ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG,
-                       SPEAR320_UART5_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0,
-                       &_lock);
+                       ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
+                       SPEAR320_EXT_CTRL_REG, SPEAR320_UART5_PCLK_SHIFT,
+                       SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
        clk_register_clkdev(clk, NULL, "60000000.serial");
 
        clk = clk_register_mux(NULL, "uart6_clk", uartx_parents,
-                       ARRAY_SIZE(uartx_parents), 0, SPEAR320_EXT_CTRL_REG,
-                       SPEAR320_UART6_PCLK_SHIFT, SPEAR320_UARTX_PCLK_MASK, 0,
-                       &_lock);
+                       ARRAY_SIZE(uartx_parents), CLK_SET_RATE_PARENT,
+                       SPEAR320_EXT_CTRL_REG, SPEAR320_UART6_PCLK_SHIFT,
+                       SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
        clk_register_clkdev(clk, NULL, "60100000.serial");
 }
+#else
+static inline void spear320_clk_init(void) { }
 #endif
 
 void __init spear3xx_clk_init(void)
 {
        struct clk *clk, *clk1;
 
-       clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
-       clk_register_clkdev(clk, "apb_pclk", NULL);
-
        clk = clk_register_fixed_rate(NULL, "osc_32k_clk", NULL, CLK_IS_ROOT,
                        32000);
        clk_register_clkdev(clk, "osc_32k_clk", NULL);
@@ -380,7 +401,8 @@ void __init spear3xx_clk_init(void)
        clk_register_clkdev(clk1, "pll2_clk", NULL);
 
        /* clock derived from pll1 clk */
-       clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk", 0, 1, 1);
+       clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk",
+                       CLK_SET_RATE_PARENT, 1, 1);
        clk_register_clkdev(clk, "cpu_clk", NULL);
 
        clk = clk_register_divider(NULL, "ahb_clk", "pll1_clk",
@@ -395,12 +417,14 @@ void __init spear3xx_clk_init(void)
        clk_register_clkdev(clk1, "uart_syn_gclk", NULL);
 
        clk = clk_register_mux(NULL, "uart0_mclk", uart0_parents,
-                       ARRAY_SIZE(uart0_parents), 0, PERIP_CLK_CFG,
-                       UART_CLK_SHIFT, UART_CLK_MASK, 0, &_lock);
+                       ARRAY_SIZE(uart0_parents), CLK_SET_RATE_PARENT,
+                       PERIP_CLK_CFG, UART_CLK_SHIFT, UART_CLK_MASK, 0,
+                       &_lock);
        clk_register_clkdev(clk, "uart0_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "uart0", "uart0_mclk", 0, PERIP1_CLK_ENB,
-                       UART_CLK_ENB, 0, &_lock);
+       clk = clk_register_gate(NULL, "uart0", "uart0_mclk",
+                       CLK_SET_RATE_PARENT, PERIP1_CLK_ENB, UART_CLK_ENB, 0,
+                       &_lock);
        clk_register_clkdev(clk, NULL, "d0000000.serial");
 
        clk = clk_register_aux("firda_syn_clk", "firda_syn_gclk", "pll1_clk", 0,
@@ -410,40 +434,44 @@ void __init spear3xx_clk_init(void)
        clk_register_clkdev(clk1, "firda_syn_gclk", NULL);
 
        clk = clk_register_mux(NULL, "firda_mclk", firda_parents,
-                       ARRAY_SIZE(firda_parents), 0, PERIP_CLK_CFG,
-                       FIRDA_CLK_SHIFT, FIRDA_CLK_MASK, 0, &_lock);
+                       ARRAY_SIZE(firda_parents), CLK_SET_RATE_PARENT,
+                       PERIP_CLK_CFG, FIRDA_CLK_SHIFT, FIRDA_CLK_MASK, 0,
+                       &_lock);
        clk_register_clkdev(clk, "firda_mclk", NULL);
 
-       clk = clk_register_gate(NULL, "firda_clk", "firda_mclk", 0,
-                       PERIP1_CLK_ENB, FIRDA_CLK_ENB, 0, &_lock);
+       clk = clk_register_gate(NULL, "firda_clk", "firda_mclk",
+                       CLK_SET_RATE_PARENT, PERIP1_CLK_ENB, FIRDA_CLK_ENB, 0,
+                       &_lock);
        clk_register_clkdev(clk, NULL, "firda");
 
        /* gpt clocks */
        clk_register_gpt("gpt0_syn_clk", "pll1_clk", 0, PRSC0_CLK_CFG, gpt_rtbl,
                        ARRAY_SIZE(gpt_rtbl), &_lock);
        clk = clk_register_mux(NULL, "gpt0_clk", gpt0_parents,
-                       ARRAY_SIZE(gpt0_parents), 0, PERIP_CLK_CFG,
-                       GPT0_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
+                       ARRAY_SIZE(gpt0_parents), CLK_SET_RATE_PARENT,
+                       PERIP_CLK_CFG, GPT0_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
        clk_register_clkdev(clk, NULL, "gpt0");
 
        clk_register_gpt("gpt1_syn_clk", "pll1_clk", 0, PRSC1_CLK_CFG, gpt_rtbl,
                        ARRAY_SIZE(gpt_rtbl), &_lock);
        clk = clk_register_mux(NULL, "gpt1_mclk", gpt1_parents,
-                       ARRAY_SIZE(gpt1_parents), 0, PERIP_CLK_CFG,
-                       GPT1_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
+                       ARRAY_SIZE(gpt1_parents), CLK_SET_RATE_PARENT,
+                       PERIP_CLK_CFG, GPT1_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
        clk_register_clkdev(clk, "gpt1_mclk", NULL);
-       clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mclk", 0,
-                       PERIP1_CLK_ENB, GPT1_CLK_ENB, 0, &_lock);
+       clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mclk",
+                       CLK_SET_RATE_PARENT, PERIP1_CLK_ENB, GPT1_CLK_ENB, 0,
+                       &_lock);
        clk_register_clkdev(clk, NULL, "gpt1");
 
        clk_register_gpt("gpt2_syn_clk", "pll1_clk", 0, PRSC2_CLK_CFG, gpt_rtbl,
                        ARRAY_SIZE(gpt_rtbl), &_lock);
        clk = clk_register_mux(NULL, "gpt2_mclk", gpt2_parents,
-                       ARRAY_SIZE(gpt2_parents), 0, PERIP_CLK_CFG,
-                       GPT2_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
+                       ARRAY_SIZE(gpt2_parents), CLK_SET_RATE_PARENT,
+                       PERIP_CLK_CFG, GPT2_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
        clk_register_clkdev(clk, "gpt2_mclk", NULL);
-       clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mclk", 0,
-                       PERIP1_CLK_ENB, GPT2_CLK_ENB, 0, &_lock);
+       clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mclk",
+                       CLK_SET_RATE_PARENT, PERIP1_CLK_ENB, GPT2_CLK_ENB, 0,
+                       &_lock);
        clk_register_clkdev(clk, NULL, "gpt2");
 
        /* general synths clocks */
@@ -480,7 +508,9 @@ void __init spear3xx_clk_init(void)
        /* clock derived from pll3 clk */
        clk = clk_register_gate(NULL, "usbh_clk", "pll3_clk", 0, PERIP1_CLK_ENB,
                        USBH_CLK_ENB, 0, &_lock);
-       clk_register_clkdev(clk, "usbh_clk", NULL);
+       clk_register_clkdev(clk, NULL, "e1800000.ehci");
+       clk_register_clkdev(clk, NULL, "e1900000.ohci");
+       clk_register_clkdev(clk, NULL, "e2100000.ohci");
 
        clk = clk_register_fixed_factor(NULL, "usbh.0_clk", "usbh_clk", 0, 1,
                        1);
@@ -492,7 +522,7 @@ void __init spear3xx_clk_init(void)
 
        clk = clk_register_gate(NULL, "usbd_clk", "pll3_clk", 0, PERIP1_CLK_ENB,
                        USBD_CLK_ENB, 0, &_lock);
-       clk_register_clkdev(clk, NULL, "designware_udc");
+       clk_register_clkdev(clk, NULL, "e1100000.usbd");
 
        /* clock derived from ahb clk */
        clk = clk_register_fixed_factor(NULL, "ahbmult2_clk", "ahb_clk", 0, 2,
@@ -540,7 +570,7 @@ void __init spear3xx_clk_init(void)
        /* clock derived from apb clk */
        clk = clk_register_gate(NULL, "adc_clk", "apb_clk", 0, PERIP1_CLK_ENB,
                        ADC_CLK_ENB, 0, &_lock);
-       clk_register_clkdev(clk, NULL, "adc");
+       clk_register_clkdev(clk, NULL, "d0080000.adc");
 
        clk = clk_register_gate(NULL, "gpio0_clk", "apb_clk", 0, PERIP1_CLK_ENB,
                        GPIO_CLK_ENB, 0, &_lock);
@@ -579,20 +609,24 @@ void __init spear3xx_clk_init(void)
                        RAS_CLK_ENB, RAS_48M_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, "ras_pll3_clk", NULL);
 
-       clk = clk_register_gate(NULL, "ras_syn0_gclk", "gen0_syn_gclk", 0,
-                       RAS_CLK_ENB, RAS_SYNT0_CLK_ENB, 0, &_lock);
+       clk = clk_register_gate(NULL, "ras_syn0_gclk", "gen0_syn_gclk",
+                       CLK_SET_RATE_PARENT, RAS_CLK_ENB, RAS_SYNT0_CLK_ENB, 0,
+                       &_lock);
        clk_register_clkdev(clk, "ras_syn0_gclk", NULL);
 
-       clk = clk_register_gate(NULL, "ras_syn1_gclk", "gen1_syn_gclk", 0,
-                       RAS_CLK_ENB, RAS_SYNT1_CLK_ENB, 0, &_lock);
+       clk = clk_register_gate(NULL, "ras_syn1_gclk", "gen1_syn_gclk",
+                       CLK_SET_RATE_PARENT, RAS_CLK_ENB, RAS_SYNT1_CLK_ENB, 0,
+                       &_lock);
        clk_register_clkdev(clk, "ras_syn1_gclk", NULL);
 
-       clk = clk_register_gate(NULL, "ras_syn2_gclk", "gen2_syn_gclk", 0,
-                       RAS_CLK_ENB, RAS_SYNT2_CLK_ENB, 0, &_lock);
+       clk = clk_register_gate(NULL, "ras_syn2_gclk", "gen2_syn_gclk",
+                       CLK_SET_RATE_PARENT, RAS_CLK_ENB, RAS_SYNT2_CLK_ENB, 0,
+                       &_lock);
        clk_register_clkdev(clk, "ras_syn2_gclk", NULL);
 
-       clk = clk_register_gate(NULL, "ras_syn3_gclk", "gen3_syn_gclk", 0,
-                       RAS_CLK_ENB, RAS_SYNT3_CLK_ENB, 0, &_lock);
+       clk = clk_register_gate(NULL, "ras_syn3_gclk", "gen3_syn_gclk",
+                       CLK_SET_RATE_PARENT, RAS_CLK_ENB, RAS_SYNT3_CLK_ENB, 0,
+                       &_lock);
        clk_register_clkdev(clk, "ras_syn3_gclk", NULL);
 
        if (of_machine_is_compatible("st,spear300"))
index a98d086..e862a33 100644 (file)
@@ -92,6 +92,7 @@ static struct pll_rate_tbl pll_rtbl[] = {
 /* aux rate configuration table, in ascending order of rates */
 static struct aux_rate_tbl aux_rtbl[] = {
        /* For PLL1 = 332 MHz */
+       {.xscale = 2, .yscale = 27, .eq = 0}, /* 12.296 MHz */
        {.xscale = 2, .yscale = 8, .eq = 0}, /* 41.5 MHz */
        {.xscale = 2, .yscale = 4, .eq = 0}, /* 83 MHz */
        {.xscale = 1, .yscale = 2, .eq = 1}, /* 166 MHz */
@@ -118,9 +119,6 @@ void __init spear6xx_clk_init(void)
 {
        struct clk *clk, *clk1;
 
-       clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
-       clk_register_clkdev(clk, "apb_pclk", NULL);
-
        clk = clk_register_fixed_rate(NULL, "osc_32k_clk", NULL, CLK_IS_ROOT,
                        32000);
        clk_register_clkdev(clk, "osc_32k_clk", NULL);
@@ -156,7 +154,8 @@ void __init spear6xx_clk_init(void)
        clk_register_clkdev(clk, NULL, "wdt");
 
        /* clock derived from pll1 clk */
-       clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk", 0, 1, 1);
+       clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk",
+                       CLK_SET_RATE_PARENT, 1, 1);
        clk_register_clkdev(clk, "cpu_clk", NULL);
 
        clk = clk_register_divider(NULL, "ahb_clk", "pll1_clk",
@@ -261,11 +260,13 @@ void __init spear6xx_clk_init(void)
        /* clock derived from pll3 clk */
        clk = clk_register_gate(NULL, "usbh0_clk", "pll3_clk", 0,
                        PERIP1_CLK_ENB, USBH0_CLK_ENB, 0, &_lock);
-       clk_register_clkdev(clk, NULL, "usbh.0_clk");
+       clk_register_clkdev(clk, NULL, "e1800000.ehci");
+       clk_register_clkdev(clk, NULL, "e1900000.ohci");
 
        clk = clk_register_gate(NULL, "usbh1_clk", "pll3_clk", 0,
                        PERIP1_CLK_ENB, USBH1_CLK_ENB, 0, &_lock);
-       clk_register_clkdev(clk, NULL, "usbh.1_clk");
+       clk_register_clkdev(clk, NULL, "e2000000.ehci");
+       clk_register_clkdev(clk, NULL, "e2100000.ohci");
 
        clk = clk_register_gate(NULL, "usbd_clk", "pll3_clk", 0, PERIP1_CLK_ENB,
                        USBD_CLK_ENB, 0, &_lock);
index 858fbfe..bcc0c11 100644 (file)
@@ -10,3 +10,6 @@ obj-y += clk-prcmu.o
 obj-y += u8500_clk.o
 obj-y += u9540_clk.o
 obj-y += u8540_clk.o
+
+# ABX500 clock driver
+obj-y += abx500-clk.o
diff --git a/drivers/clk/ux500/abx500-clk.c b/drivers/clk/ux500/abx500-clk.c
new file mode 100644 (file)
index 0000000..e27c523
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * abx500 clock implementation for ux500 platform.
+ *
+ * Copyright (C) 2012 ST-Ericsson SA
+ * Author: Ulf Hansson <ulf.hansson@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/abx500/ab8500.h>
+
+/* TODO: Add clock implementations here */
+
+
+/* Clock definitions for ab8500 */
+static int ab8500_reg_clks(struct device *dev)
+{
+       return 0;
+}
+
+/* Clock definitions for ab8540 */
+static int ab8540_reg_clks(struct device *dev)
+{
+       return 0;
+}
+
+/* Clock definitions for ab9540 */
+static int ab9540_reg_clks(struct device *dev)
+{
+       return 0;
+}
+
+static int __devinit abx500_clk_probe(struct platform_device *pdev)
+{
+       struct ab8500 *parent = dev_get_drvdata(pdev->dev.parent);
+       int ret;
+
+       if (is_ab8500(parent) || is_ab8505(parent)) {
+               ret = ab8500_reg_clks(&pdev->dev);
+       } else if (is_ab8540(parent)) {
+               ret = ab8540_reg_clks(&pdev->dev);
+       } else if (is_ab9540(parent)) {
+               ret = ab9540_reg_clks(&pdev->dev);
+       } else {
+               dev_err(&pdev->dev, "non supported plf id\n");
+               return -ENODEV;
+       }
+
+       return ret;
+}
+
+static struct platform_driver abx500_clk_driver = {
+       .driver = {
+               .name = "abx500-clk",
+               .owner = THIS_MODULE,
+       },
+       .probe  = abx500_clk_probe,
+};
+
+static int __init abx500_clk_init(void)
+{
+       return platform_driver_register(&abx500_clk_driver);
+}
+
+arch_initcall(abx500_clk_init);
+
+MODULE_AUTHOR("Ulf Hansson <ulf.hansson@linaro.org");
+MODULE_DESCRIPTION("ABX500 clk driver");
+MODULE_LICENSE("GPL v2");
index 930cdfe..74faa7e 100644 (file)
@@ -133,6 +133,40 @@ out_error:
                hw->init->name);
 }
 
+static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw)
+{
+       int err;
+       struct clk_prcmu *clk = to_clk_prcmu(hw);
+
+       err = prcmu_request_ape_opp_100_voltage(true);
+       if (err) {
+               pr_err("clk_prcmu: %s failed to request APE OPP VOLT for %s.\n",
+                       __func__, hw->init->name);
+               return err;
+       }
+
+       err = prcmu_request_clock(clk->cg_sel, true);
+       if (err)
+               prcmu_request_ape_opp_100_voltage(false);
+
+       return err;
+}
+
+static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw)
+{
+       struct clk_prcmu *clk = to_clk_prcmu(hw);
+
+       if (prcmu_request_clock(clk->cg_sel, false))
+               goto out_error;
+       if (prcmu_request_ape_opp_100_voltage(false))
+               goto out_error;
+       return;
+
+out_error:
+       pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
+               hw->init->name);
+}
+
 static struct clk_ops clk_prcmu_scalable_ops = {
        .prepare = clk_prcmu_prepare,
        .unprepare = clk_prcmu_unprepare,
@@ -153,6 +187,13 @@ static struct clk_ops clk_prcmu_gate_ops = {
        .recalc_rate = clk_prcmu_recalc_rate,
 };
 
+static struct clk_ops clk_prcmu_scalable_rate_ops = {
+       .is_enabled = clk_prcmu_is_enabled,
+       .recalc_rate = clk_prcmu_recalc_rate,
+       .round_rate = clk_prcmu_round_rate,
+       .set_rate = clk_prcmu_set_rate,
+};
+
 static struct clk_ops clk_prcmu_rate_ops = {
        .is_enabled = clk_prcmu_is_enabled,
        .recalc_rate = clk_prcmu_recalc_rate,
@@ -167,6 +208,17 @@ static struct clk_ops clk_prcmu_opp_gate_ops = {
        .recalc_rate = clk_prcmu_recalc_rate,
 };
 
+static struct clk_ops clk_prcmu_opp_volt_scalable_ops = {
+       .prepare = clk_prcmu_opp_volt_prepare,
+       .unprepare = clk_prcmu_opp_volt_unprepare,
+       .enable = clk_prcmu_enable,
+       .disable = clk_prcmu_disable,
+       .is_enabled = clk_prcmu_is_enabled,
+       .recalc_rate = clk_prcmu_recalc_rate,
+       .round_rate = clk_prcmu_round_rate,
+       .set_rate = clk_prcmu_set_rate,
+};
+
 static struct clk *clk_reg_prcmu(const char *name,
                                 const char *parent_name,
                                 u8 cg_sel,
@@ -233,6 +285,16 @@ struct clk *clk_reg_prcmu_gate(const char *name,
                        &clk_prcmu_gate_ops);
 }
 
+struct clk *clk_reg_prcmu_scalable_rate(const char *name,
+                                       const char *parent_name,
+                                       u8 cg_sel,
+                                       unsigned long rate,
+                                       unsigned long flags)
+{
+       return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
+                       &clk_prcmu_scalable_rate_ops);
+}
+
 struct clk *clk_reg_prcmu_rate(const char *name,
                               const char *parent_name,
                               u8 cg_sel,
@@ -250,3 +312,13 @@ struct clk *clk_reg_prcmu_opp_gate(const char *name,
        return clk_reg_prcmu(name, parent_name, cg_sel, 0, flags,
                        &clk_prcmu_opp_gate_ops);
 }
+
+struct clk *clk_reg_prcmu_opp_volt_scalable(const char *name,
+                                           const char *parent_name,
+                                           u8 cg_sel,
+                                           unsigned long rate,
+                                           unsigned long flags)
+{
+       return clk_reg_prcmu(name, parent_name, cg_sel, rate, flags,
+                       &clk_prcmu_opp_volt_scalable_ops);
+}
index 836d7d1..c3e4491 100644 (file)
@@ -35,6 +35,12 @@ struct clk *clk_reg_prcmu_gate(const char *name,
                               u8 cg_sel,
                               unsigned long flags);
 
+struct clk *clk_reg_prcmu_scalable_rate(const char *name,
+                                       const char *parent_name,
+                                       u8 cg_sel,
+                                       unsigned long rate,
+                                       unsigned long flags);
+
 struct clk *clk_reg_prcmu_rate(const char *name,
                               const char *parent_name,
                               u8 cg_sel,
@@ -45,4 +51,10 @@ struct clk *clk_reg_prcmu_opp_gate(const char *name,
                                   u8 cg_sel,
                                   unsigned long flags);
 
+struct clk *clk_reg_prcmu_opp_volt_scalable(const char *name,
+                                           const char *parent_name,
+                                           u8 cg_sel,
+                                           unsigned long rate,
+                                           unsigned long flags);
+
 #endif /* __UX500_CLK_H */
index ca4a25e..7d0e025 100644 (file)
@@ -40,7 +40,7 @@ void u8500_clk_init(void)
                                CLK_IS_ROOT|CLK_IGNORE_UNUSED,
                                32768);
        clk_register_clkdev(clk, "clk32k", NULL);
-       clk_register_clkdev(clk, NULL, "rtc-pl031");
+       clk_register_clkdev(clk, "apb_pclk", "rtc-pl031");
 
        /* PRCMU clocks */
        fw_version = prcmu_get_fw_version();
@@ -170,10 +170,11 @@ void u8500_clk_init(void)
        clk_register_clkdev(clk, NULL, "mtu0");
        clk_register_clkdev(clk, NULL, "mtu1");
 
-       clk = clk_reg_prcmu_gate("sdmmcclk", NULL, PRCMU_SDMMCCLK, CLK_IS_ROOT);
+       clk = clk_reg_prcmu_opp_volt_scalable("sdmmcclk", NULL, PRCMU_SDMMCCLK,
+                                       100000000,
+                                       CLK_IS_ROOT|CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, NULL, "sdmmc");
 
-
        clk = clk_reg_prcmu_scalable("dsi_pll", "hdmiclk",
                                PRCMU_PLLDSI, 0, CLK_SET_RATE_GATE);
        clk_register_clkdev(clk, "dsihs2", "mcde");
@@ -205,16 +206,18 @@ void u8500_clk_init(void)
        clk_register_clkdev(clk, "dsilp2", "dsilink.2");
        clk_register_clkdev(clk, "dsilp2", "mcde");
 
-       clk = clk_reg_prcmu_rate("smp_twd", NULL, PRCMU_ARMSS,
-                               CLK_IS_ROOT|CLK_GET_RATE_NOCACHE|
-                               CLK_IGNORE_UNUSED);
+       clk = clk_reg_prcmu_scalable_rate("armss", NULL,
+                               PRCMU_ARMSS, 0, CLK_IS_ROOT|CLK_IGNORE_UNUSED);
+       clk_register_clkdev(clk, "armss", NULL);
+
+       clk = clk_register_fixed_factor(NULL, "smp_twd", "armss",
+                               CLK_IGNORE_UNUSED, 1, 2);
        clk_register_clkdev(clk, NULL, "smp_twd");
 
        /*
         * FIXME: Add special handled PRCMU clocks here:
-        * 1. clk_arm, use PRCMU_ARMCLK.
-        * 2. clkout0yuv, use PRCMU as parent + need regulator + pinctrl.
-        * 3. ab9540_clkout1yuv, see clkout0yuv
+        * 1. clkout0yuv, use PRCMU as parent + need regulator + pinctrl.
+        * 2. ab9540_clkout1yuv, see clkout0yuv
         */
 
        /* PRCC P-clocks */
@@ -228,10 +231,17 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", U8500_CLKRST1_BASE,
                                BIT(2), 0);
+       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.1");
+
        clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", U8500_CLKRST1_BASE,
                                BIT(3), 0);
+       clk_register_clkdev(clk, "apb_pclk", "msp0");
+       clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.0");
+
        clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", U8500_CLKRST1_BASE,
                                BIT(4), 0);
+       clk_register_clkdev(clk, "apb_pclk", "msp1");
+       clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.1");
 
        clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", U8500_CLKRST1_BASE,
                                BIT(5), 0);
@@ -239,6 +249,7 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", U8500_CLKRST1_BASE,
                                BIT(6), 0);
+       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.2");
 
        clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", U8500_CLKRST1_BASE,
                                BIT(7), 0);
@@ -246,6 +257,7 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", U8500_CLKRST1_BASE,
                                BIT(8), 0);
+       clk_register_clkdev(clk, "apb_pclk", "slimbus0");
 
        clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", U8500_CLKRST1_BASE,
                                BIT(9), 0);
@@ -255,11 +267,16 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", U8500_CLKRST1_BASE,
                                BIT(10), 0);
+       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.4");
+
        clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", U8500_CLKRST1_BASE,
                                BIT(11), 0);
+       clk_register_clkdev(clk, "apb_pclk", "msp3");
+       clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.3");
 
        clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", U8500_CLKRST2_BASE,
                                BIT(0), 0);
+       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.3");
 
        clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", U8500_CLKRST2_BASE,
                                BIT(1), 0);
@@ -279,12 +296,13 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", U8500_CLKRST2_BASE,
                                BIT(5), 0);
+       clk_register_clkdev(clk, "apb_pclk", "msp2");
+       clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.2");
 
        clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", U8500_CLKRST2_BASE,
                                BIT(6), 0);
        clk_register_clkdev(clk, "apb_pclk", "sdi1");
 
-
        clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", U8500_CLKRST2_BASE,
                                BIT(7), 0);
        clk_register_clkdev(clk, "apb_pclk", "sdi3");
@@ -308,7 +326,7 @@ void u8500_clk_init(void)
        clk_register_clkdev(clk, NULL, "gpioblock1");
 
        clk = clk_reg_prcc_pclk("p2_pclk12", "per2clk", U8500_CLKRST2_BASE,
-                               BIT(11), 0);
+                               BIT(12), 0);
 
        clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", U8500_CLKRST3_BASE,
                                BIT(0), 0);
@@ -316,10 +334,15 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", U8500_CLKRST3_BASE,
                                BIT(1), 0);
+       clk_register_clkdev(clk, "apb_pclk", "ssp0");
+
        clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", U8500_CLKRST3_BASE,
                                BIT(2), 0);
+       clk_register_clkdev(clk, "apb_pclk", "ssp1");
+
        clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", U8500_CLKRST3_BASE,
                                BIT(3), 0);
+       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.0");
 
        clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", U8500_CLKRST3_BASE,
                                BIT(4), 0);
@@ -327,6 +350,8 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", U8500_CLKRST3_BASE,
                                BIT(5), 0);
+       clk_register_clkdev(clk, "apb_pclk", "ske");
+       clk_register_clkdev(clk, "apb_pclk", "nmk-ske-keypad");
 
        clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", U8500_CLKRST3_BASE,
                                BIT(6), 0);
@@ -355,6 +380,7 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", U8500_CLKRST6_BASE,
                                BIT(0), 0);
+       clk_register_clkdev(clk, "apb_pclk", "rng");
 
        clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", U8500_CLKRST6_BASE,
                                BIT(1), 0);
@@ -401,10 +427,17 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_kclk("p1_i2c1_kclk", "i2cclk",
                        U8500_CLKRST1_BASE, BIT(2), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "nmk-i2c.1");
+
        clk = clk_reg_prcc_kclk("p1_msp0_kclk", "msp02clk",
                        U8500_CLKRST1_BASE, BIT(3), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "msp0");
+       clk_register_clkdev(clk, NULL, "ux500-msp-i2s.0");
+
        clk = clk_reg_prcc_kclk("p1_msp1_kclk", "msp1clk",
                        U8500_CLKRST1_BASE, BIT(4), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "msp1");
+       clk_register_clkdev(clk, NULL, "ux500-msp-i2s.1");
 
        clk = clk_reg_prcc_kclk("p1_sdi0_kclk", "sdmmcclk",
                        U8500_CLKRST1_BASE, BIT(5), CLK_SET_RATE_GATE);
@@ -412,17 +445,25 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_kclk("p1_i2c2_kclk", "i2cclk",
                        U8500_CLKRST1_BASE, BIT(6), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "nmk-i2c.2");
+
        clk = clk_reg_prcc_kclk("p1_slimbus0_kclk", "slimclk",
-                       U8500_CLKRST1_BASE, BIT(3), CLK_SET_RATE_GATE);
-       /* FIXME: Redefinition of BIT(3). */
+                       U8500_CLKRST1_BASE, BIT(8), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "slimbus0");
+
        clk = clk_reg_prcc_kclk("p1_i2c4_kclk", "i2cclk",
                        U8500_CLKRST1_BASE, BIT(9), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "nmk-i2c.4");
+
        clk = clk_reg_prcc_kclk("p1_msp3_kclk", "msp1clk",
                        U8500_CLKRST1_BASE, BIT(10), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "msp3");
+       clk_register_clkdev(clk, NULL, "ux500-msp-i2s.3");
 
        /* Periph2 */
        clk = clk_reg_prcc_kclk("p2_i2c3_kclk", "i2cclk",
                        U8500_CLKRST2_BASE, BIT(0), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "nmk-i2c.3");
 
        clk = clk_reg_prcc_kclk("p2_sdi4_kclk", "sdmmcclk",
                        U8500_CLKRST2_BASE, BIT(2), CLK_SET_RATE_GATE);
@@ -430,6 +471,8 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_kclk("p2_msp2_kclk", "msp02clk",
                        U8500_CLKRST2_BASE, BIT(3), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "msp2");
+       clk_register_clkdev(clk, NULL, "ux500-msp-i2s.2");
 
        clk = clk_reg_prcc_kclk("p2_sdi1_kclk", "sdmmcclk",
                        U8500_CLKRST2_BASE, BIT(4), CLK_SET_RATE_GATE);
@@ -450,10 +493,15 @@ void u8500_clk_init(void)
        /* Periph3 */
        clk = clk_reg_prcc_kclk("p3_ssp0_kclk", "sspclk",
                        U8500_CLKRST3_BASE, BIT(1), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "ssp0");
+
        clk = clk_reg_prcc_kclk("p3_ssp1_kclk", "sspclk",
                        U8500_CLKRST3_BASE, BIT(2), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "ssp1");
+
        clk = clk_reg_prcc_kclk("p3_i2c0_kclk", "i2cclk",
                        U8500_CLKRST3_BASE, BIT(3), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "nmk-i2c.0");
 
        clk = clk_reg_prcc_kclk("p3_sdi2_kclk", "sdmmcclk",
                        U8500_CLKRST3_BASE, BIT(4), CLK_SET_RATE_GATE);
@@ -461,6 +509,8 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_kclk("p3_ske_kclk", "rtc32k",
                        U8500_CLKRST3_BASE, BIT(5), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "ske");
+       clk_register_clkdev(clk, NULL, "nmk-ske-keypad");
 
        clk = clk_reg_prcc_kclk("p3_uart2_kclk", "uartclk",
                        U8500_CLKRST3_BASE, BIT(6), CLK_SET_RATE_GATE);
@@ -473,5 +523,5 @@ void u8500_clk_init(void)
        /* Periph6 */
        clk = clk_reg_prcc_kclk("p3_rng_kclk", "rngclk",
                        U8500_CLKRST6_BASE, BIT(0), CLK_SET_RATE_GATE);
-
+       clk_register_clkdev(clk, NULL, "rng");
 }
index c0a0f64..ec3b88f 100644 (file)
@@ -1,4 +1,7 @@
 # Makefile for Versatile-specific clocks
 obj-$(CONFIG_ICST)             += clk-icst.o
 obj-$(CONFIG_ARCH_INTEGRATOR)  += clk-integrator.o
+obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o
 obj-$(CONFIG_ARCH_REALVIEW)    += clk-realview.o
+obj-$(CONFIG_ARCH_VEXPRESS)    += clk-vexpress.o
+obj-$(CONFIG_VEXPRESS_CONFIG)  += clk-vexpress-osc.o
index f555b50..67ccf4a 100644 (file)
@@ -3,6 +3,12 @@
  * We wrap the custom interface from <asm/hardware/icst.h> into the generic
  * clock framework.
  *
+ * Copyright (C) 2012 Linus Walleij
+ *
+ * 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.
+ *
  * TODO: when all ARM reference designs are migrated to generic clocks, the
  * ICST clock code from the ARM tree should probably be merged into this
  * file.
 #include <linux/clkdev.h>
 #include <linux/err.h>
 #include <linux/clk-provider.h>
+#include <linux/io.h>
 
 #include "clk-icst.h"
 
 /**
  * struct clk_icst - ICST VCO clock wrapper
  * @hw: corresponding clock hardware entry
+ * @vcoreg: VCO register address
+ * @lockreg: VCO lock register address
  * @params: parameters for this ICST instance
  * @rate: current rate
- * @setvco: function to commit ICST settings to hardware
  */
 struct clk_icst {
        struct clk_hw hw;
+       void __iomem *vcoreg;
+       void __iomem *lockreg;
        const struct icst_params *params;
        unsigned long rate;
-       struct icst_vco (*getvco)(void);
-       void (*setvco)(struct icst_vco);
 };
 
 #define to_icst(_hw) container_of(_hw, struct clk_icst, hw)
 
+/**
+ * vco_get() - get ICST VCO settings from a certain register
+ * @vcoreg: register containing the VCO settings
+ */
+static struct icst_vco vco_get(void __iomem *vcoreg)
+{
+       u32 val;
+       struct icst_vco vco;
+
+       val = readl(vcoreg);
+       vco.v = val & 0x1ff;
+       vco.r = (val >> 9) & 0x7f;
+       vco.s = (val >> 16) & 03;
+       return vco;
+}
+
+/**
+ * vco_set() - commit changes to an ICST VCO
+ * @locreg: register to poke to unlock the VCO for writing
+ * @vcoreg: register containing the VCO settings
+ * @vco: ICST VCO parameters to commit
+ */
+static void vco_set(void __iomem *lockreg,
+                       void __iomem *vcoreg,
+                       struct icst_vco vco)
+{
+       u32 val;
+
+       val = readl(vcoreg) & ~0x7ffff;
+       val |= vco.v | (vco.r << 9) | (vco.s << 16);
+
+       /* This magic unlocks the VCO so it can be controlled */
+       writel(0xa05f, lockreg);
+       writel(val, vcoreg);
+       /* This locks the VCO again */
+       writel(0, lockreg);
+}
+
+
 static unsigned long icst_recalc_rate(struct clk_hw *hw,
                                      unsigned long parent_rate)
 {
        struct clk_icst *icst = to_icst(hw);
        struct icst_vco vco;
 
-       vco = icst->getvco();
+       vco = vco_get(icst->vcoreg);
        icst->rate = icst_hz(icst->params, vco);
        return icst->rate;
 }
@@ -60,7 +107,7 @@ static int icst_set_rate(struct clk_hw *hw, unsigned long rate,
 
        vco = icst_hz_to_vco(icst->params, rate);
        icst->rate = icst_hz(icst->params, vco);
-       icst->setvco(vco);
+       vco_set(icst->vcoreg, icst->lockreg, vco);
        return 0;
 }
 
@@ -70,8 +117,9 @@ static const struct clk_ops icst_ops = {
        .set_rate = icst_set_rate,
 };
 
-struct clk * __init icst_clk_register(struct device *dev,
-                                     const struct clk_icst_desc *desc)
+struct clk *icst_clk_register(struct device *dev,
+                       const struct clk_icst_desc *desc,
+                       void __iomem *base)
 {
        struct clk *clk;
        struct clk_icst *icst;
@@ -89,8 +137,8 @@ struct clk * __init icst_clk_register(struct device *dev,
        init.num_parents = 0;
        icst->hw.init = &init;
        icst->params = desc->params;
-       icst->getvco = desc->getvco;
-       icst->setvco = desc->setvco;
+       icst->vcoreg = base + desc->vco_offset;
+       icst->lockreg = base + desc->lock_offset;
 
        clk = clk_register(dev, &icst->hw);
        if (IS_ERR(clk))
index 71b4c56..dad51b6 100644 (file)
@@ -1,10 +1,18 @@
 #include <asm/hardware/icst.h>
 
+/**
+ * struct clk_icst_desc - descriptor for the ICST VCO
+ * @params: ICST parameters
+ * @vco_offset: offset to the ICST VCO from the provided memory base
+ * @lock_offset: offset to the ICST VCO locking register from the provided
+ *     memory base
+ */
 struct clk_icst_desc {
        const struct icst_params *params;
-       struct icst_vco (*getvco)(void);
-       void (*setvco)(struct icst_vco);
+       u32 vco_offset;
+       u32 lock_offset;
 };
 
 struct clk *icst_clk_register(struct device *dev,
-                             const struct clk_icst_desc *desc);
+                             const struct clk_icst_desc *desc,
+                             void __iomem *base);
diff --git a/drivers/clk/versatile/clk-impd1.c b/drivers/clk/versatile/clk-impd1.c
new file mode 100644 (file)
index 0000000..369139a
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Clock driver for the ARM Integrator/IM-PD1 board
+ * Copyright (C) 2012 Linus Walleij
+ *
+ * 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/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/platform_data/clk-integrator.h>
+
+#include <mach/impd1.h>
+
+#include "clk-icst.h"
+
+struct impd1_clk {
+       struct clk *vcoclk;
+       struct clk *uartclk;
+       struct clk_lookup *clks[3];
+};
+
+static struct impd1_clk impd1_clks[4];
+
+/*
+ * There are two VCO's on the IM-PD1 but only one is used by the
+ * kernel, that is why we are only implementing the control of
+ * IMPD1_OSC1 here.
+ */
+
+static const struct icst_params impd1_vco_params = {
+       .ref            = 24000000,     /* 24 MHz */
+       .vco_max        = ICST525_VCO_MAX_3V,
+       .vco_min        = ICST525_VCO_MIN,
+       .vd_min         = 12,
+       .vd_max         = 519,
+       .rd_min         = 3,
+       .rd_max         = 120,
+       .s2div          = icst525_s2div,
+       .idx2s          = icst525_idx2s,
+};
+
+static const struct clk_icst_desc impd1_icst1_desc = {
+       .params = &impd1_vco_params,
+       .vco_offset = IMPD1_OSC1,
+       .lock_offset = IMPD1_LOCK,
+};
+
+/**
+ * integrator_impd1_clk_init() - set up the integrator clock tree
+ * @base: base address of the logic module (LM)
+ * @id: the ID of this LM
+ */
+void integrator_impd1_clk_init(void __iomem *base, unsigned int id)
+{
+       struct impd1_clk *imc;
+       struct clk *clk;
+       int i;
+
+       if (id > 3) {
+               pr_crit("no more than 4 LMs can be attached\n");
+               return;
+       }
+       imc = &impd1_clks[id];
+
+       clk = icst_clk_register(NULL, &impd1_icst1_desc, base);
+       imc->vcoclk = clk;
+       imc->clks[0] = clkdev_alloc(clk, NULL, "lm%x:01000", id);
+
+       /* UART reference clock */
+       clk = clk_register_fixed_rate(NULL, "uartclk", NULL, CLK_IS_ROOT,
+                               14745600);
+       imc->uartclk = clk;
+       imc->clks[1] = clkdev_alloc(clk, NULL, "lm%x:00100", id);
+       imc->clks[2] = clkdev_alloc(clk, NULL, "lm%x:00200", id);
+
+       for (i = 0; i < ARRAY_SIZE(imc->clks); i++)
+               clkdev_add(imc->clks[i]);
+}
+
+void integrator_impd1_clk_exit(unsigned int id)
+{
+       int i;
+       struct impd1_clk *imc;
+
+       if (id > 3)
+               return;
+       imc = &impd1_clks[id];
+
+       for (i = 0; i < ARRAY_SIZE(imc->clks); i++)
+               clkdev_drop(imc->clks[i]);
+       clk_unregister(imc->uartclk);
+       clk_unregister(imc->vcoclk);
+}
index a505392..08593b4 100644 (file)
@@ -1,8 +1,16 @@
+/*
+ * Clock driver for the ARM Integrator/AP and Integrator/CP boards
+ * Copyright (C) 2012 Linus Walleij
+ *
+ * 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/clk-provider.h>
 #include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/err.h>
-#include <linux/io.h>
-#include <linux/clk-provider.h>
+#include <linux/platform_data/clk-integrator.h>
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
  * Inspired by portions of:
  * plat-versatile/clock.c and plat-versatile/include/plat/clock.h
  */
-#define CM_LOCK                (__io_address(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_LOCK_OFFSET)
-#define CM_AUXOSC      (__io_address(INTEGRATOR_HDR_BASE)+0x1c)
-
-/**
- * cp_auxvco_get() - get ICST VCO settings for the Integrator/CP
- * @vco: ICST VCO parameters to update with hardware status
- */
-static struct icst_vco cp_auxvco_get(void)
-{
-       u32 val;
-       struct icst_vco vco;
-
-       val = readl(CM_AUXOSC);
-       vco.v = val & 0x1ff;
-       vco.r = (val >> 9) & 0x7f;
-       vco.s = (val >> 16) & 03;
-       return vco;
-}
-
-/**
- * cp_auxvco_set() - commit changes to Integrator/CP ICST VCO
- * @vco: ICST VCO parameters to commit
- */
-static void cp_auxvco_set(struct icst_vco vco)
-{
-       u32 val;
-
-       val = readl(CM_AUXOSC) & ~0x7ffff;
-       val |= vco.v | (vco.r << 9) | (vco.s << 16);
-
-       /* This magic unlocks the CM VCO so it can be controlled */
-       writel(0xa05f, CM_LOCK);
-       writel(val, CM_AUXOSC);
-       /* This locks the CM again */
-       writel(0, CM_LOCK);
-}
 
 static const struct icst_params cp_auxvco_params = {
        .ref            = 24000000,
@@ -65,8 +37,8 @@ static const struct icst_params cp_auxvco_params = {
 
 static const struct clk_icst_desc __initdata cp_icst_desc = {
        .params = &cp_auxvco_params,
-       .getvco = cp_auxvco_get,
-       .setvco = cp_auxvco_set,
+       .vco_offset = 0x1c,
+       .lock_offset = INTEGRATOR_HDR_LOCK_OFFSET,
 };
 
 /*
@@ -106,6 +78,7 @@ void __init integrator_clk_init(bool is_cp)
        clk_register_clkdev(clk, NULL, "sp804");
 
        /* ICST VCO clock used on the Integrator/CP CLCD */
-       clk = icst_clk_register(NULL, &cp_icst_desc);
+       clk = icst_clk_register(NULL, &cp_icst_desc,
+                               __io_address(INTEGRATOR_HDR_BASE));
        clk_register_clkdev(clk, NULL, "clcd");
 }
index e21a99c..cda07e7 100644 (file)
@@ -1,3 +1,11 @@
+/*
+ * Clock driver for the ARM RealView boards
+ * Copyright (C) 2012 Linus Walleij
+ *
+ * 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/clk.h>
 #include <linux/clkdev.h>
 #include <linux/err.h>
  * Implementation of the ARM RealView clock trees.
  */
 
-static void __iomem *sys_lock;
-static void __iomem *sys_vcoreg;
-
-/**
- * realview_oscvco_get() - get ICST OSC settings for the RealView
- */
-static struct icst_vco realview_oscvco_get(void)
-{
-       u32 val;
-       struct icst_vco vco;
-
-       val = readl(sys_vcoreg);
-       vco.v = val & 0x1ff;
-       vco.r = (val >> 9) & 0x7f;
-       vco.s = (val >> 16) & 03;
-       return vco;
-}
-
-static void realview_oscvco_set(struct icst_vco vco)
-{
-       u32 val;
-
-       val = readl(sys_vcoreg) & ~0x7ffff;
-       val |= vco.v | (vco.r << 9) | (vco.s << 16);
-
-       /* This magic unlocks the CM VCO so it can be controlled */
-       writel(0xa05f, sys_lock);
-       writel(val, sys_vcoreg);
-       /* This locks the CM again */
-       writel(0, sys_lock);
-}
-
 static const struct icst_params realview_oscvco_params = {
        .ref            = 24000000,
        .vco_max        = ICST307_VCO_MAX,
@@ -57,10 +33,16 @@ static const struct icst_params realview_oscvco_params = {
        .idx2s          = icst307_idx2s,
 };
 
-static const struct clk_icst_desc __initdata realview_icst_desc = {
+static const struct clk_icst_desc __initdata realview_osc0_desc = {
+       .params = &realview_oscvco_params,
+       .vco_offset = REALVIEW_SYS_OSC0_OFFSET,
+       .lock_offset = REALVIEW_SYS_LOCK_OFFSET,
+};
+
+static const struct clk_icst_desc __initdata realview_osc4_desc = {
        .params = &realview_oscvco_params,
-       .getvco = realview_oscvco_get,
-       .setvco = realview_oscvco_set,
+       .vco_offset = REALVIEW_SYS_OSC4_OFFSET,
+       .lock_offset = REALVIEW_SYS_LOCK_OFFSET,
 };
 
 /*
@@ -70,13 +52,6 @@ void __init realview_clk_init(void __iomem *sysbase, bool is_pb1176)
 {
        struct clk *clk;
 
-       sys_lock = sysbase + REALVIEW_SYS_LOCK_OFFSET;
-       if (is_pb1176)
-               sys_vcoreg = sysbase + REALVIEW_SYS_OSC0_OFFSET;
-       else
-               sys_vcoreg = sysbase + REALVIEW_SYS_OSC4_OFFSET;
-
-
        /* APB clock dummy */
        clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
        clk_register_clkdev(clk, "apb_pclk", NULL);
@@ -108,7 +83,11 @@ void __init realview_clk_init(void __iomem *sysbase, bool is_pb1176)
        clk_register_clkdev(clk, NULL, "sp804");
 
        /* ICST VCO clock */
-       clk = icst_clk_register(NULL, &realview_icst_desc);
+       if (is_pb1176)
+               clk = icst_clk_register(NULL, &realview_osc0_desc, sysbase);
+       else
+               clk = icst_clk_register(NULL, &realview_osc4_desc, sysbase);
+
        clk_register_clkdev(clk, NULL, "dev:clcd");
        clk_register_clkdev(clk, NULL, "issp:clcd");
 }
diff --git a/drivers/clk/versatile/clk-vexpress-osc.c b/drivers/clk/versatile/clk-vexpress-osc.c
new file mode 100644 (file)
index 0000000..dcb6ae0
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * 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 pr_fmt(fmt) "vexpress-osc: " fmt
+
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/vexpress.h>
+
+struct vexpress_osc {
+       struct vexpress_config_func *func;
+       struct clk_hw hw;
+       unsigned long rate_min;
+       unsigned long rate_max;
+};
+
+#define to_vexpress_osc(osc) container_of(osc, struct vexpress_osc, hw)
+
+static unsigned long vexpress_osc_recalc_rate(struct clk_hw *hw,
+               unsigned long parent_rate)
+{
+       struct vexpress_osc *osc = to_vexpress_osc(hw);
+       u32 rate;
+
+       vexpress_config_read(osc->func, 0, &rate);
+
+       return rate;
+}
+
+static long vexpress_osc_round_rate(struct clk_hw *hw, unsigned long rate,
+               unsigned long *parent_rate)
+{
+       struct vexpress_osc *osc = to_vexpress_osc(hw);
+
+       if (WARN_ON(osc->rate_min && rate < osc->rate_min))
+               rate = osc->rate_min;
+
+       if (WARN_ON(osc->rate_max && rate > osc->rate_max))
+               rate = osc->rate_max;
+
+       return rate;
+}
+
+static int vexpress_osc_set_rate(struct clk_hw *hw, unsigned long rate,
+               unsigned long parent_rate)
+{
+       struct vexpress_osc *osc = to_vexpress_osc(hw);
+
+       return vexpress_config_write(osc->func, 0, rate);
+}
+
+static struct clk_ops vexpress_osc_ops = {
+       .recalc_rate = vexpress_osc_recalc_rate,
+       .round_rate = vexpress_osc_round_rate,
+       .set_rate = vexpress_osc_set_rate,
+};
+
+
+struct clk * __init vexpress_osc_setup(struct device *dev)
+{
+       struct clk_init_data init;
+       struct vexpress_osc *osc = kzalloc(sizeof(*osc), GFP_KERNEL);
+
+       if (!osc)
+               return NULL;
+
+       osc->func = vexpress_config_func_get_by_dev(dev);
+       if (!osc->func) {
+               kfree(osc);
+               return NULL;
+       }
+
+       init.name = dev_name(dev);
+       init.ops = &vexpress_osc_ops;
+       init.flags = CLK_IS_ROOT;
+       init.num_parents = 0;
+       osc->hw.init = &init;
+
+       return clk_register(NULL, &osc->hw);
+}
+
+void __init vexpress_osc_of_setup(struct device_node *node)
+{
+       struct clk_init_data init;
+       struct vexpress_osc *osc;
+       struct clk *clk;
+       u32 range[2];
+
+       osc = kzalloc(sizeof(*osc), GFP_KERNEL);
+       if (!osc)
+               goto error;
+
+       osc->func = vexpress_config_func_get_by_node(node);
+       if (!osc->func) {
+               pr_err("Failed to obtain config func for node '%s'!\n",
+                               node->name);
+               goto error;
+       }
+
+       if (of_property_read_u32_array(node, "freq-range", range,
+                       ARRAY_SIZE(range)) == 0) {
+               osc->rate_min = range[0];
+               osc->rate_max = range[1];
+       }
+
+       of_property_read_string(node, "clock-output-names", &init.name);
+       if (!init.name)
+               init.name = node->name;
+
+       init.ops = &vexpress_osc_ops;
+       init.flags = CLK_IS_ROOT;
+       init.num_parents = 0;
+
+       osc->hw.init = &init;
+
+       clk = clk_register(NULL, &osc->hw);
+       if (IS_ERR(clk)) {
+               pr_err("Failed to register clock '%s'!\n", init.name);
+               goto error;
+       }
+
+       of_clk_add_provider(node, of_clk_src_simple_get, clk);
+
+       pr_debug("Registered clock '%s'\n", init.name);
+
+       return;
+
+error:
+       if (osc->func)
+               vexpress_config_func_put(osc->func);
+       kfree(osc);
+}
diff --git a/drivers/clk/versatile/clk-vexpress.c b/drivers/clk/versatile/clk-vexpress.c
new file mode 100644 (file)
index 0000000..c742ac7
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * 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
+ */
+
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/vexpress.h>
+
+#include <asm/hardware/sp810.h>
+
+static struct clk *vexpress_sp810_timerclken[4];
+static DEFINE_SPINLOCK(vexpress_sp810_lock);
+
+static void __init vexpress_sp810_init(void __iomem *base)
+{
+       int i;
+
+       if (WARN_ON(!base))
+               return;
+
+       for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++) {
+               char name[12];
+               const char *parents[] = {
+                       "v2m:refclk32khz", /* REFCLK */
+                       "v2m:refclk1mhz" /* TIMCLK */
+               };
+
+               snprintf(name, ARRAY_SIZE(name), "timerclken%d", i);
+
+               vexpress_sp810_timerclken[i] = clk_register_mux(NULL, name,
+                               parents, 2, 0, base + SCCTRL,
+                               SCCTRL_TIMERENnSEL_SHIFT(i), 1,
+                               0, &vexpress_sp810_lock);
+
+               if (WARN_ON(IS_ERR(vexpress_sp810_timerclken[i])))
+                       break;
+       }
+}
+
+
+static const char * const vexpress_clk_24mhz_periphs[] __initconst = {
+       "mb:uart0", "mb:uart1", "mb:uart2", "mb:uart3",
+       "mb:mmci", "mb:kmi0", "mb:kmi1"
+};
+
+void __init vexpress_clk_init(void __iomem *sp810_base)
+{
+       struct clk *clk;
+       int i;
+
+       clk = clk_register_fixed_rate(NULL, "dummy_apb_pclk", NULL,
+                       CLK_IS_ROOT, 0);
+       WARN_ON(clk_register_clkdev(clk, "apb_pclk", NULL));
+
+       clk = clk_register_fixed_rate(NULL, "v2m:clk_24mhz", NULL,
+                       CLK_IS_ROOT, 24000000);
+       for (i = 0; i < ARRAY_SIZE(vexpress_clk_24mhz_periphs); i++)
+               WARN_ON(clk_register_clkdev(clk, NULL,
+                               vexpress_clk_24mhz_periphs[i]));
+
+       clk = clk_register_fixed_rate(NULL, "v2m:refclk32khz", NULL,
+                       CLK_IS_ROOT, 32768);
+       WARN_ON(clk_register_clkdev(clk, NULL, "v2m:wdt"));
+
+       clk = clk_register_fixed_rate(NULL, "v2m:refclk1mhz", NULL,
+                       CLK_IS_ROOT, 1000000);
+
+       vexpress_sp810_init(sp810_base);
+
+       for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++)
+               WARN_ON(clk_set_parent(vexpress_sp810_timerclken[i], clk));
+
+       WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[0],
+                               "v2m-timer0", "sp804"));
+       WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[1],
+                               "v2m-timer1", "sp804"));
+}
+
+#if defined(CONFIG_OF)
+
+struct clk *vexpress_sp810_of_get(struct of_phandle_args *clkspec, void *data)
+{
+       if (WARN_ON(clkspec->args_count != 1 || clkspec->args[0] >
+                       ARRAY_SIZE(vexpress_sp810_timerclken)))
+               return NULL;
+
+       return vexpress_sp810_timerclken[clkspec->args[0]];
+}
+
+static const __initconst struct of_device_id vexpress_fixed_clk_match[] = {
+       { .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
+       { .compatible = "arm,vexpress-osc", .data = vexpress_osc_of_setup, },
+       {}
+};
+
+void __init vexpress_clk_of_init(void)
+{
+       struct device_node *node;
+       struct clk *clk;
+       struct clk *refclk, *timclk;
+
+       of_clk_init(vexpress_fixed_clk_match);
+
+       node = of_find_compatible_node(NULL, NULL, "arm,sp810");
+       vexpress_sp810_init(of_iomap(node, 0));
+       of_clk_add_provider(node, vexpress_sp810_of_get, NULL);
+
+       /* Select "better" (faster) parent for SP804 timers */
+       refclk = of_clk_get_by_name(node, "refclk");
+       timclk = of_clk_get_by_name(node, "timclk");
+       if (!WARN_ON(IS_ERR(refclk) || IS_ERR(timclk))) {
+               int i = 0;
+
+               if (clk_get_rate(refclk) > clk_get_rate(timclk))
+                       clk = refclk;
+               else
+                       clk = timclk;
+
+               for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++)
+                       WARN_ON(clk_set_parent(vexpress_sp810_timerclken[i],
+                                       clk));
+       }
+
+       WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[0],
+                               "v2m-timer0", "sp804"));
+       WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[1],
+                               "v2m-timer1", "sp804"));
+}
+
+#endif
index 5961e64..a0b3661 100644 (file)
@@ -76,3 +76,10 @@ config ARM_EXYNOS5250_CPUFREQ
        help
          This adds the CPUFreq driver for Samsung EXYNOS5250
          SoC.
+
+config ARM_SPEAR_CPUFREQ
+       bool "SPEAr CPUFreq support"
+       depends on PLAT_SPEAR
+       default y
+       help
+         This adds the CPUFreq driver support for SPEAr SOCs.
index 1bc90e1..1f254ec 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
@@ -50,6 +50,7 @@ obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ)  += exynos4210-cpufreq.o
 obj-$(CONFIG_ARM_EXYNOS4X12_CPUFREQ)   += exynos4x12-cpufreq.o
 obj-$(CONFIG_ARM_EXYNOS5250_CPUFREQ)   += exynos5250-cpufreq.o
 obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ)     += omap-cpufreq.o
+obj-$(CONFIG_ARM_SPEAR_CPUFREQ)                += spear-cpufreq.o
 
 ##################################################################################
 # PowerPC platform drivers
index e915827..52bf36d 100644 (file)
@@ -174,7 +174,7 @@ static struct cpufreq_driver cpu0_cpufreq_driver = {
        .attr = cpu0_cpufreq_attr,
 };
 
-static int __devinit cpu0_cpufreq_driver_init(void)
+static int cpu0_cpufreq_driver_init(void)
 {
        struct device_node *np;
        int ret;
index fb8a527..1f93dbd 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>
@@ -127,7 +129,7 @@ static int __init init_cpufreq_transition_notifier_list(void)
 pure_initcall(init_cpufreq_transition_notifier_list);
 
 static int off __read_mostly;
-int cpufreq_disabled(void)
+static int cpufreq_disabled(void)
 {
        return off;
 }
@@ -402,7 +404,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
 static ssize_t store_##file_name                                       \
 (struct cpufreq_policy *policy, const char *buf, size_t count)         \
 {                                                                      \
-       unsigned int ret = -EINVAL;                                     \
+       unsigned int ret;                                               \
        struct cpufreq_policy new_policy;                               \
                                                                        \
        ret = cpufreq_get_policy(&new_policy, policy->cpu);             \
@@ -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;
 }
@@ -457,7 +459,7 @@ static ssize_t show_scaling_governor(struct cpufreq_policy *policy, char *buf)
 static ssize_t store_scaling_governor(struct cpufreq_policy *policy,
                                        const char *buf, size_t count)
 {
-       unsigned int ret = -EINVAL;
+       unsigned int ret;
        char    str_governor[16];
        struct cpufreq_policy new_policy;
 
@@ -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)
 {
@@ -1468,12 +1470,23 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
                            unsigned int relation)
 {
        int retval = -EINVAL;
+       unsigned int old_target_freq = target_freq;
 
        if (cpufreq_disabled())
                return -ENODEV;
 
-       pr_debug("target for CPU %u: %u kHz, relation %u\n", policy->cpu,
-               target_freq, relation);
+       /* Make sure that target_freq is within supported range */
+       if (target_freq > policy->max)
+               target_freq = policy->max;
+       if (target_freq < policy->min)
+               target_freq = policy->min;
+
+       pr_debug("target for CPU %u: %u kHz, relation %u, requested %u kHz\n",
+                       policy->cpu, target_freq, relation, old_target_freq);
+
+       if (target_freq == policy->cur)
+               return 0;
+
        if (cpu_online(policy->cpu) && cpufreq_driver->target)
                retval = cpufreq_driver->target(policy, target_freq, relation);
 
@@ -1509,12 +1522,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 a152af7..64ef737 100644 (file)
  * published by the Free Software Foundation.
  */
 
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
 #include <linux/cpufreq.h>
-#include <linux/cpu.h>
-#include <linux/jiffies.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/kernel_stat.h>
+#include <linux/kobject.h>
+#include <linux/module.h>
 #include <linux/mutex.h>
-#include <linux/hrtimer.h>
-#include <linux/tick.h>
-#include <linux/ktime.h>
-#include <linux/sched.h>
+#include <linux/notifier.h>
+#include <linux/percpu-defs.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
 
-/*
- * dbs is used in this file as a shortform for demandbased switching
- * It helps to keep variable names smaller, simpler
- */
+#include "cpufreq_governor.h"
 
+/* Conservative governor macors */
 #define DEF_FREQUENCY_UP_THRESHOLD             (80)
 #define DEF_FREQUENCY_DOWN_THRESHOLD           (20)
-
-/*
- * The polling frequency of this governor depends on the capability of
- * the processor. Default polling frequency is 1000 times the transition
- * latency of the processor. The governor will work on any processor with
- * transition latency <= 10mS, using appropriate sampling
- * rate.
- * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL)
- * this governor will not work.
- * All times here are in uS.
- */
-#define MIN_SAMPLING_RATE_RATIO                        (2)
-
-static unsigned int min_sampling_rate;
-
-#define LATENCY_MULTIPLIER                     (1000)
-#define MIN_LATENCY_MULTIPLIER                 (100)
 #define DEF_SAMPLING_DOWN_FACTOR               (1)
 #define MAX_SAMPLING_DOWN_FACTOR               (10)
-#define TRANSITION_LATENCY_LIMIT               (10 * 1000 * 1000)
-
-static void do_dbs_timer(struct work_struct *work);
-
-struct cpu_dbs_info_s {
-       cputime64_t prev_cpu_idle;
-       cputime64_t prev_cpu_wall;
-       cputime64_t prev_cpu_nice;
-       struct cpufreq_policy *cur_policy;
-       struct delayed_work work;
-       unsigned int down_skip;
-       unsigned int requested_freq;
-       int cpu;
-       unsigned int enable:1;
-       /*
-        * percpu mutex that serializes governor limit change with
-        * do_dbs_timer invocation. We do not want do_dbs_timer to run
-        * when user is changing the governor or limits.
-        */
-       struct mutex timer_mutex;
-};
-static DEFINE_PER_CPU(struct cpu_dbs_info_s, cs_cpu_dbs_info);
 
-static unsigned int dbs_enable;        /* number of CPUs using this policy */
+static struct dbs_data cs_dbs_data;
+static DEFINE_PER_CPU(struct cs_cpu_dbs_info_s, cs_cpu_dbs_info);
 
-/*
- * dbs_mutex protects dbs_enable in governor start/stop.
- */
-static DEFINE_MUTEX(dbs_mutex);
-
-static struct dbs_tuners {
-       unsigned int sampling_rate;
-       unsigned int sampling_down_factor;
-       unsigned int up_threshold;
-       unsigned int down_threshold;
-       unsigned int ignore_nice;
-       unsigned int freq_step;
-} dbs_tuners_ins = {
+static struct cs_dbs_tuners cs_tuners = {
        .up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
        .down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD,
        .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
@@ -95,95 +42,121 @@ static struct dbs_tuners {
        .freq_step = 5,
 };
 
-static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
+/*
+ * Every sampling_rate, we check, if current idle time is less than 20%
+ * (default), then we try to increase frequency Every sampling_rate *
+ * sampling_down_factor, we check, if current idle time is more than 80%, then
+ * we try to decrease frequency
+ *
+ * Any frequency increase takes it to the maximum frequency. Frequency reduction
+ * happens at minimum steps of 5% (default) of maximum frequency
+ */
+static void cs_check_cpu(int cpu, unsigned int load)
 {
-       u64 idle_time;
-       u64 cur_wall_time;
-       u64 busy_time;
+       struct cs_cpu_dbs_info_s *dbs_info = &per_cpu(cs_cpu_dbs_info, cpu);
+       struct cpufreq_policy *policy = dbs_info->cdbs.cur_policy;
+       unsigned int freq_target;
+
+       /*
+        * break out if we 'cannot' reduce the speed as the user might
+        * want freq_step to be zero
+        */
+       if (cs_tuners.freq_step == 0)
+               return;
 
-       cur_wall_time = jiffies64_to_cputime64(get_jiffies_64());
+       /* Check for frequency increase */
+       if (load > cs_tuners.up_threshold) {
+               dbs_info->down_skip = 0;
 
-       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];
+               /* if we are already at full speed then break out early */
+               if (dbs_info->requested_freq == policy->max)
+                       return;
 
-       idle_time = cur_wall_time - busy_time;
-       if (wall)
-               *wall = jiffies_to_usecs(cur_wall_time);
+               freq_target = (cs_tuners.freq_step * policy->max) / 100;
 
-       return jiffies_to_usecs(idle_time);
+               /* max freq cannot be less than 100. But who knows.... */
+               if (unlikely(freq_target == 0))
+                       freq_target = 5;
+
+               dbs_info->requested_freq += freq_target;
+               if (dbs_info->requested_freq > policy->max)
+                       dbs_info->requested_freq = policy->max;
+
+               __cpufreq_driver_target(policy, dbs_info->requested_freq,
+                       CPUFREQ_RELATION_H);
+               return;
+       }
+
+       /*
+        * The optimal frequency is the frequency that is the lowest that can
+        * support the current CPU usage without triggering the up policy. To be
+        * safe, we focus 10 points under the threshold.
+        */
+       if (load < (cs_tuners.down_threshold - 10)) {
+               freq_target = (cs_tuners.freq_step * policy->max) / 100;
+
+               dbs_info->requested_freq -= freq_target;
+               if (dbs_info->requested_freq < policy->min)
+                       dbs_info->requested_freq = policy->min;
+
+               /*
+                * if we cannot reduce the frequency anymore, break out early
+                */
+               if (policy->cur == policy->min)
+                       return;
+
+               __cpufreq_driver_target(policy, dbs_info->requested_freq,
+                               CPUFREQ_RELATION_H);
+               return;
+       }
 }
 
-static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
+static void cs_dbs_timer(struct work_struct *work)
 {
-       u64 idle_time = get_cpu_idle_time_us(cpu, NULL);
+       struct cs_cpu_dbs_info_s *dbs_info = container_of(work,
+                       struct cs_cpu_dbs_info_s, cdbs.work.work);
+       unsigned int cpu = dbs_info->cdbs.cpu;
+       int delay = delay_for_sampling_rate(cs_tuners.sampling_rate);
 
-       if (idle_time == -1ULL)
-               return get_cpu_idle_time_jiffy(cpu, wall);
-       else
-               idle_time += get_cpu_iowait_time_us(cpu, wall);
+       mutex_lock(&dbs_info->cdbs.timer_mutex);
 
-       return idle_time;
+       dbs_check_cpu(&cs_dbs_data, cpu);
+
+       schedule_delayed_work_on(cpu, &dbs_info->cdbs.work, delay);
+       mutex_unlock(&dbs_info->cdbs.timer_mutex);
 }
 
-/* keep track of frequency transitions */
-static int
-dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
-                    void *data)
+static int dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
+               void *data)
 {
        struct cpufreq_freqs *freq = data;
-       struct cpu_dbs_info_s *this_dbs_info = &per_cpu(cs_cpu_dbs_info,
-                                                       freq->cpu);
-
+       struct cs_cpu_dbs_info_s *dbs_info =
+                                       &per_cpu(cs_cpu_dbs_info, freq->cpu);
        struct cpufreq_policy *policy;
 
-       if (!this_dbs_info->enable)
+       if (!dbs_info->enable)
                return 0;
 
-       policy = this_dbs_info->cur_policy;
+       policy = dbs_info->cdbs.cur_policy;
 
        /*
-        * we only care if our internally tracked freq moves outside
-        * the 'valid' ranges of freqency available to us otherwise
-        * we do not change it
+        * we only care if our internally tracked freq moves outside the 'valid'
+        * ranges of freqency available to us otherwise we do not change it
        */
-       if (this_dbs_info->requested_freq > policy->max
-                       || this_dbs_info->requested_freq < policy->min)
-               this_dbs_info->requested_freq = freq->new;
+       if (dbs_info->requested_freq > policy->max
+                       || dbs_info->requested_freq < policy->min)
+               dbs_info->requested_freq = freq->new;
 
        return 0;
 }
 
-static struct notifier_block dbs_cpufreq_notifier_block = {
-       .notifier_call = dbs_cpufreq_notifier
-};
-
 /************************** sysfs interface ************************/
 static ssize_t show_sampling_rate_min(struct kobject *kobj,
                                      struct attribute *attr, char *buf)
 {
-       return sprintf(buf, "%u\n", min_sampling_rate);
+       return sprintf(buf, "%u\n", cs_dbs_data.min_sampling_rate);
 }
 
-define_one_global_ro(sampling_rate_min);
-
-/* cpufreq_conservative Governor Tunables */
-#define show_one(file_name, object)                                    \
-static ssize_t show_##file_name                                                \
-(struct kobject *kobj, struct attribute *attr, char *buf)              \
-{                                                                      \
-       return sprintf(buf, "%u\n", dbs_tuners_ins.object);             \
-}
-show_one(sampling_rate, sampling_rate);
-show_one(sampling_down_factor, sampling_down_factor);
-show_one(up_threshold, up_threshold);
-show_one(down_threshold, down_threshold);
-show_one(ignore_nice_load, ignore_nice);
-show_one(freq_step, freq_step);
-
 static ssize_t store_sampling_down_factor(struct kobject *a,
                                          struct attribute *b,
                                          const char *buf, size_t count)
@@ -195,7 +168,7 @@ static ssize_t store_sampling_down_factor(struct kobject *a,
        if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
                return -EINVAL;
 
-       dbs_tuners_ins.sampling_down_factor = input;
+       cs_tuners.sampling_down_factor = input;
        return count;
 }
 
@@ -209,7 +182,7 @@ static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,
        if (ret != 1)
                return -EINVAL;
 
-       dbs_tuners_ins.sampling_rate = max(input, min_sampling_rate);
+       cs_tuners.sampling_rate = max(input, cs_dbs_data.min_sampling_rate);
        return count;
 }
 
@@ -220,11 +193,10 @@ static ssize_t store_up_threshold(struct kobject *a, struct attribute *b,
        int ret;
        ret = sscanf(buf, "%u", &input);
 
-       if (ret != 1 || input > 100 ||
-                       input <= dbs_tuners_ins.down_threshold)
+       if (ret != 1 || input > 100 || input <= cs_tuners.down_threshold)
                return -EINVAL;
 
-       dbs_tuners_ins.up_threshold = input;
+       cs_tuners.up_threshold = input;
        return count;
 }
 
@@ -237,21 +209,19 @@ static ssize_t store_down_threshold(struct kobject *a, struct attribute *b,
 
        /* cannot be lower than 11 otherwise freq will not fall */
        if (ret != 1 || input < 11 || input > 100 ||
-                       input >= dbs_tuners_ins.up_threshold)
+                       input >= cs_tuners.up_threshold)
                return -EINVAL;
 
-       dbs_tuners_ins.down_threshold = input;
+       cs_tuners.down_threshold = input;
        return count;
 }
 
 static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
                                      const char *buf, size_t count)
 {
-       unsigned int input;
+       unsigned int input, j;
        int ret;
 
-       unsigned int j;
-
        ret = sscanf(buf, "%u", &input);
        if (ret != 1)
                return -EINVAL;
@@ -259,19 +229,20 @@ static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
        if (input > 1)
                input = 1;
 
-       if (input == dbs_tuners_ins.ignore_nice) /* nothing to do */
+       if (input == cs_tuners.ignore_nice) /* nothing to do */
                return count;
 
-       dbs_tuners_ins.ignore_nice = input;
+       cs_tuners.ignore_nice = input;
 
        /* we need to re-evaluate prev_cpu_idle */
        for_each_online_cpu(j) {
-               struct cpu_dbs_info_s *dbs_info;
+               struct cs_cpu_dbs_info_s *dbs_info;
                dbs_info = &per_cpu(cs_cpu_dbs_info, j);
-               dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
-                                               &dbs_info->prev_cpu_wall);
-               if (dbs_tuners_ins.ignore_nice)
-                       dbs_info->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE];
+               dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j,
+                                               &dbs_info->cdbs.prev_cpu_wall);
+               if (cs_tuners.ignore_nice)
+                       dbs_info->cdbs.prev_cpu_nice =
+                               kcpustat_cpu(j).cpustat[CPUTIME_NICE];
        }
        return count;
 }
@@ -289,18 +260,28 @@ static ssize_t store_freq_step(struct kobject *a, struct attribute *b,
        if (input > 100)
                input = 100;
 
-       /* no need to test here if freq_step is zero as the user might actually
-        * want this, they would be crazy though :) */
-       dbs_tuners_ins.freq_step = input;
+       /*
+        * no need to test here if freq_step is zero as the user might actually
+        * want this, they would be crazy though :)
+        */
+       cs_tuners.freq_step = input;
        return count;
 }
 
+show_one(cs, sampling_rate, sampling_rate);
+show_one(cs, sampling_down_factor, sampling_down_factor);
+show_one(cs, up_threshold, up_threshold);
+show_one(cs, down_threshold, down_threshold);
+show_one(cs, ignore_nice_load, ignore_nice);
+show_one(cs, freq_step, freq_step);
+
 define_one_global_rw(sampling_rate);
 define_one_global_rw(sampling_down_factor);
 define_one_global_rw(up_threshold);
 define_one_global_rw(down_threshold);
 define_one_global_rw(ignore_nice_load);
 define_one_global_rw(freq_step);
+define_one_global_ro(sampling_rate_min);
 
 static struct attribute *dbs_attributes[] = {
        &sampling_rate_min.attr,
@@ -313,283 +294,38 @@ static struct attribute *dbs_attributes[] = {
        NULL
 };
 
-static struct attribute_group dbs_attr_group = {
+static struct attribute_group cs_attr_group = {
        .attrs = dbs_attributes,
        .name = "conservative",
 };
 
 /************************** sysfs end ************************/
 
-static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
-{
-       unsigned int load = 0;
-       unsigned int max_load = 0;
-       unsigned int freq_target;
-
-       struct cpufreq_policy *policy;
-       unsigned int j;
-
-       policy = this_dbs_info->cur_policy;
-
-       /*
-        * Every sampling_rate, we check, if current idle time is less
-        * than 20% (default), then we try to increase frequency
-        * Every sampling_rate*sampling_down_factor, we check, if current
-        * idle time is more than 80%, then we try to decrease frequency
-        *
-        * Any frequency increase takes it to the maximum frequency.
-        * Frequency reduction happens at minimum steps of
-        * 5% (default) of maximum frequency
-        */
-
-       /* Get Absolute Load */
-       for_each_cpu(j, policy->cpus) {
-               struct cpu_dbs_info_s *j_dbs_info;
-               cputime64_t cur_wall_time, cur_idle_time;
-               unsigned int idle_time, wall_time;
-
-               j_dbs_info = &per_cpu(cs_cpu_dbs_info, j);
-
-               cur_idle_time = get_cpu_idle_time(j, &cur_wall_time);
-
-               wall_time = (unsigned int)
-                       (cur_wall_time - j_dbs_info->prev_cpu_wall);
-               j_dbs_info->prev_cpu_wall = cur_wall_time;
-
-               idle_time = (unsigned int)
-                       (cur_idle_time - j_dbs_info->prev_cpu_idle);
-               j_dbs_info->prev_cpu_idle = cur_idle_time;
-
-               if (dbs_tuners_ins.ignore_nice) {
-                       u64 cur_nice;
-                       unsigned long cur_nice_jiffies;
-
-                       cur_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE] -
-                                        j_dbs_info->prev_cpu_nice;
-                       /*
-                        * Assumption: nice time between sampling periods will
-                        * be less than 2^32 jiffies for 32 bit sys
-                        */
-                       cur_nice_jiffies = (unsigned long)
-                                       cputime64_to_jiffies64(cur_nice);
-
-                       j_dbs_info->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE];
-                       idle_time += jiffies_to_usecs(cur_nice_jiffies);
-               }
+define_get_cpu_dbs_routines(cs_cpu_dbs_info);
 
-               if (unlikely(!wall_time || wall_time < idle_time))
-                       continue;
-
-               load = 100 * (wall_time - idle_time) / wall_time;
-
-               if (load > max_load)
-                       max_load = load;
-       }
-
-       /*
-        * break out if we 'cannot' reduce the speed as the user might
-        * want freq_step to be zero
-        */
-       if (dbs_tuners_ins.freq_step == 0)
-               return;
-
-       /* Check for frequency increase */
-       if (max_load > dbs_tuners_ins.up_threshold) {
-               this_dbs_info->down_skip = 0;
-
-               /* if we are already at full speed then break out early */
-               if (this_dbs_info->requested_freq == policy->max)
-                       return;
-
-               freq_target = (dbs_tuners_ins.freq_step * policy->max) / 100;
-
-               /* max freq cannot be less than 100. But who knows.... */
-               if (unlikely(freq_target == 0))
-                       freq_target = 5;
-
-               this_dbs_info->requested_freq += freq_target;
-               if (this_dbs_info->requested_freq > policy->max)
-                       this_dbs_info->requested_freq = policy->max;
-
-               __cpufreq_driver_target(policy, this_dbs_info->requested_freq,
-                       CPUFREQ_RELATION_H);
-               return;
-       }
-
-       /*
-        * The optimal frequency is the frequency that is the lowest that
-        * can support the current CPU usage without triggering the up
-        * policy. To be safe, we focus 10 points under the threshold.
-        */
-       if (max_load < (dbs_tuners_ins.down_threshold - 10)) {
-               freq_target = (dbs_tuners_ins.freq_step * policy->max) / 100;
-
-               this_dbs_info->requested_freq -= freq_target;
-               if (this_dbs_info->requested_freq < policy->min)
-                       this_dbs_info->requested_freq = policy->min;
-
-               /*
-                * if we cannot reduce the frequency anymore, break out early
-                */
-               if (policy->cur == policy->min)
-                       return;
-
-               __cpufreq_driver_target(policy, this_dbs_info->requested_freq,
-                               CPUFREQ_RELATION_H);
-               return;
-       }
-}
-
-static void do_dbs_timer(struct work_struct *work)
-{
-       struct cpu_dbs_info_s *dbs_info =
-               container_of(work, struct cpu_dbs_info_s, work.work);
-       unsigned int cpu = dbs_info->cpu;
-
-       /* We want all CPUs to do sampling nearly on same jiffy */
-       int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
-
-       delay -= jiffies % delay;
-
-       mutex_lock(&dbs_info->timer_mutex);
-
-       dbs_check_cpu(dbs_info);
-
-       schedule_delayed_work_on(cpu, &dbs_info->work, delay);
-       mutex_unlock(&dbs_info->timer_mutex);
-}
-
-static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
-{
-       /* We want all CPUs to do sampling nearly on same jiffy */
-       int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
-       delay -= jiffies % delay;
+static struct notifier_block cs_cpufreq_notifier_block = {
+       .notifier_call = dbs_cpufreq_notifier,
+};
 
-       dbs_info->enable = 1;
-       INIT_DEFERRABLE_WORK(&dbs_info->work, do_dbs_timer);
-       schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work, delay);
-}
+static struct cs_ops cs_ops = {
+       .notifier_block = &cs_cpufreq_notifier_block,
+};
 
-static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
-{
-       dbs_info->enable = 0;
-       cancel_delayed_work_sync(&dbs_info->work);
-}
+static struct dbs_data cs_dbs_data = {
+       .governor = GOV_CONSERVATIVE,
+       .attr_group = &cs_attr_group,
+       .tuners = &cs_tuners,
+       .get_cpu_cdbs = get_cpu_cdbs,
+       .get_cpu_dbs_info_s = get_cpu_dbs_info_s,
+       .gov_dbs_timer = cs_dbs_timer,
+       .gov_check_cpu = cs_check_cpu,
+       .gov_ops = &cs_ops,
+};
 
-static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
+static int cs_cpufreq_governor_dbs(struct cpufreq_policy *policy,
                                   unsigned int event)
 {
-       unsigned int cpu = policy->cpu;
-       struct cpu_dbs_info_s *this_dbs_info;
-       unsigned int j;
-       int rc;
-
-       this_dbs_info = &per_cpu(cs_cpu_dbs_info, cpu);
-
-       switch (event) {
-       case CPUFREQ_GOV_START:
-               if ((!cpu_online(cpu)) || (!policy->cur))
-                       return -EINVAL;
-
-               mutex_lock(&dbs_mutex);
-
-               for_each_cpu(j, policy->cpus) {
-                       struct cpu_dbs_info_s *j_dbs_info;
-                       j_dbs_info = &per_cpu(cs_cpu_dbs_info, j);
-                       j_dbs_info->cur_policy = policy;
-
-                       j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
-                                               &j_dbs_info->prev_cpu_wall);
-                       if (dbs_tuners_ins.ignore_nice)
-                               j_dbs_info->prev_cpu_nice =
-                                               kcpustat_cpu(j).cpustat[CPUTIME_NICE];
-               }
-               this_dbs_info->cpu = cpu;
-               this_dbs_info->down_skip = 0;
-               this_dbs_info->requested_freq = policy->cur;
-
-               mutex_init(&this_dbs_info->timer_mutex);
-               dbs_enable++;
-               /*
-                * Start the timerschedule work, when this governor
-                * is used for first time
-                */
-               if (dbs_enable == 1) {
-                       unsigned int latency;
-                       /* policy latency is in nS. Convert it to uS first */
-                       latency = policy->cpuinfo.transition_latency / 1000;
-                       if (latency == 0)
-                               latency = 1;
-
-                       rc = sysfs_create_group(cpufreq_global_kobject,
-                                               &dbs_attr_group);
-                       if (rc) {
-                               mutex_unlock(&dbs_mutex);
-                               return rc;
-                       }
-
-                       /*
-                        * conservative does not implement micro like ondemand
-                        * governor, thus we are bound to jiffes/HZ
-                        */
-                       min_sampling_rate =
-                               MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10);
-                       /* Bring kernel and HW constraints together */
-                       min_sampling_rate = max(min_sampling_rate,
-                                       MIN_LATENCY_MULTIPLIER * latency);
-                       dbs_tuners_ins.sampling_rate =
-                               max(min_sampling_rate,
-                                   latency * LATENCY_MULTIPLIER);
-
-                       cpufreq_register_notifier(
-                                       &dbs_cpufreq_notifier_block,
-                                       CPUFREQ_TRANSITION_NOTIFIER);
-               }
-               mutex_unlock(&dbs_mutex);
-
-               dbs_timer_init(this_dbs_info);
-
-               break;
-
-       case CPUFREQ_GOV_STOP:
-               dbs_timer_exit(this_dbs_info);
-
-               mutex_lock(&dbs_mutex);
-               dbs_enable--;
-               mutex_destroy(&this_dbs_info->timer_mutex);
-
-               /*
-                * Stop the timerschedule work, when this governor
-                * is used for first time
-                */
-               if (dbs_enable == 0)
-                       cpufreq_unregister_notifier(
-                                       &dbs_cpufreq_notifier_block,
-                                       CPUFREQ_TRANSITION_NOTIFIER);
-
-               mutex_unlock(&dbs_mutex);
-               if (!dbs_enable)
-                       sysfs_remove_group(cpufreq_global_kobject,
-                                          &dbs_attr_group);
-
-               break;
-
-       case CPUFREQ_GOV_LIMITS:
-               mutex_lock(&this_dbs_info->timer_mutex);
-               if (policy->max < this_dbs_info->cur_policy->cur)
-                       __cpufreq_driver_target(
-                                       this_dbs_info->cur_policy,
-                                       policy->max, CPUFREQ_RELATION_H);
-               else if (policy->min > this_dbs_info->cur_policy->cur)
-                       __cpufreq_driver_target(
-                                       this_dbs_info->cur_policy,
-                                       policy->min, CPUFREQ_RELATION_L);
-               dbs_check_cpu(this_dbs_info);
-               mutex_unlock(&this_dbs_info->timer_mutex);
-
-               break;
-       }
-       return 0;
+       return cpufreq_governor_dbs(&cs_dbs_data, policy, event);
 }
 
 #ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
@@ -597,13 +333,14 @@ static
 #endif
 struct cpufreq_governor cpufreq_gov_conservative = {
        .name                   = "conservative",
-       .governor               = cpufreq_governor_dbs,
+       .governor               = cs_cpufreq_governor_dbs,
        .max_transition_latency = TRANSITION_LATENCY_LIMIT,
        .owner                  = THIS_MODULE,
 };
 
 static int __init cpufreq_gov_dbs_init(void)
 {
+       mutex_init(&cs_dbs_data.mutex);
        return cpufreq_register_governor(&cpufreq_gov_conservative);
 }
 
@@ -612,7 +349,6 @@ static void __exit cpufreq_gov_dbs_exit(void)
        cpufreq_unregister_governor(&cpufreq_gov_conservative);
 }
 
-
 MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>");
 MODULE_DESCRIPTION("'cpufreq_conservative' - A dynamic cpufreq governor for "
                "Low Latency Frequency Transition capable processors "
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
new file mode 100644 (file)
index 0000000..6c5f1d3
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+ * drivers/cpufreq/cpufreq_governor.c
+ *
+ * CPUFREQ governors common code
+ *
+ * Copyright   (C) 2001 Russell King
+ *             (C) 2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>.
+ *             (C) 2003 Jun Nakajima <jun.nakajima@intel.com>
+ *             (C) 2009 Alexander Clouter <alex@digriz.org.uk>
+ *             (c) 2012 Viresh Kumar <viresh.kumar@linaro.org>
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <asm/cputime.h>
+#include <linux/cpufreq.h>
+#include <linux/cpumask.h>
+#include <linux/export.h>
+#include <linux/kernel_stat.h>
+#include <linux/mutex.h>
+#include <linux/tick.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+#include "cpufreq_governor.h"
+
+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);
+}
+
+u64 get_cpu_idle_time(unsigned int cpu, u64 *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);
+
+void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
+{
+       struct cpu_dbs_common_info *cdbs = dbs_data->get_cpu_cdbs(cpu);
+       struct od_dbs_tuners *od_tuners = dbs_data->tuners;
+       struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
+       struct cpufreq_policy *policy;
+       unsigned int max_load = 0;
+       unsigned int ignore_nice;
+       unsigned int j;
+
+       if (dbs_data->governor == GOV_ONDEMAND)
+               ignore_nice = od_tuners->ignore_nice;
+       else
+               ignore_nice = cs_tuners->ignore_nice;
+
+       policy = cdbs->cur_policy;
+
+       /* Get Absolute Load (in terms of freq for ondemand gov) */
+       for_each_cpu(j, policy->cpus) {
+               struct cpu_dbs_common_info *j_cdbs;
+               u64 cur_wall_time, cur_idle_time, cur_iowait_time;
+               unsigned int idle_time, wall_time, iowait_time;
+               unsigned int load;
+
+               j_cdbs = dbs_data->get_cpu_cdbs(j);
+
+               cur_idle_time = get_cpu_idle_time(j, &cur_wall_time);
+
+               wall_time = (unsigned int)
+                       (cur_wall_time - j_cdbs->prev_cpu_wall);
+               j_cdbs->prev_cpu_wall = cur_wall_time;
+
+               idle_time = (unsigned int)
+                       (cur_idle_time - j_cdbs->prev_cpu_idle);
+               j_cdbs->prev_cpu_idle = cur_idle_time;
+
+               if (ignore_nice) {
+                       u64 cur_nice;
+                       unsigned long cur_nice_jiffies;
+
+                       cur_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE] -
+                                        cdbs->prev_cpu_nice;
+                       /*
+                        * Assumption: nice time between sampling periods will
+                        * be less than 2^32 jiffies for 32 bit sys
+                        */
+                       cur_nice_jiffies = (unsigned long)
+                                       cputime64_to_jiffies64(cur_nice);
+
+                       cdbs->prev_cpu_nice =
+                               kcpustat_cpu(j).cpustat[CPUTIME_NICE];
+                       idle_time += jiffies_to_usecs(cur_nice_jiffies);
+               }
+
+               if (dbs_data->governor == GOV_ONDEMAND) {
+                       struct od_cpu_dbs_info_s *od_j_dbs_info =
+                               dbs_data->get_cpu_dbs_info_s(cpu);
+
+                       cur_iowait_time = get_cpu_iowait_time_us(j,
+                                       &cur_wall_time);
+                       if (cur_iowait_time == -1ULL)
+                               cur_iowait_time = 0;
+
+                       iowait_time = (unsigned int) (cur_iowait_time -
+                                       od_j_dbs_info->prev_cpu_iowait);
+                       od_j_dbs_info->prev_cpu_iowait = cur_iowait_time;
+
+                       /*
+                        * For the purpose of ondemand, waiting for disk IO is
+                        * an indication that you're performance critical, and
+                        * not that the system is actually idle. So subtract the
+                        * iowait time from the cpu idle time.
+                        */
+                       if (od_tuners->io_is_busy && idle_time >= iowait_time)
+                               idle_time -= iowait_time;
+               }
+
+               if (unlikely(!wall_time || wall_time < idle_time))
+                       continue;
+
+               load = 100 * (wall_time - idle_time) / wall_time;
+
+               if (dbs_data->governor == GOV_ONDEMAND) {
+                       int freq_avg = __cpufreq_driver_getavg(policy, j);
+                       if (freq_avg <= 0)
+                               freq_avg = policy->cur;
+
+                       load *= freq_avg;
+               }
+
+               if (load > max_load)
+                       max_load = load;
+       }
+
+       dbs_data->gov_check_cpu(cpu, max_load);
+}
+EXPORT_SYMBOL_GPL(dbs_check_cpu);
+
+static inline void dbs_timer_init(struct dbs_data *dbs_data,
+               struct cpu_dbs_common_info *cdbs, unsigned int sampling_rate)
+{
+       int delay = delay_for_sampling_rate(sampling_rate);
+
+       INIT_DEFERRABLE_WORK(&cdbs->work, dbs_data->gov_dbs_timer);
+       schedule_delayed_work_on(cdbs->cpu, &cdbs->work, delay);
+}
+
+static inline void dbs_timer_exit(struct cpu_dbs_common_info *cdbs)
+{
+       cancel_delayed_work_sync(&cdbs->work);
+}
+
+int cpufreq_governor_dbs(struct dbs_data *dbs_data,
+               struct cpufreq_policy *policy, unsigned int event)
+{
+       struct od_cpu_dbs_info_s *od_dbs_info = NULL;
+       struct cs_cpu_dbs_info_s *cs_dbs_info = NULL;
+       struct od_dbs_tuners *od_tuners = dbs_data->tuners;
+       struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
+       struct cpu_dbs_common_info *cpu_cdbs;
+       unsigned int *sampling_rate, latency, ignore_nice, j, cpu = policy->cpu;
+       int rc;
+
+       cpu_cdbs = dbs_data->get_cpu_cdbs(cpu);
+
+       if (dbs_data->governor == GOV_CONSERVATIVE) {
+               cs_dbs_info = dbs_data->get_cpu_dbs_info_s(cpu);
+               sampling_rate = &cs_tuners->sampling_rate;
+               ignore_nice = cs_tuners->ignore_nice;
+       } else {
+               od_dbs_info = dbs_data->get_cpu_dbs_info_s(cpu);
+               sampling_rate = &od_tuners->sampling_rate;
+               ignore_nice = od_tuners->ignore_nice;
+       }
+
+       switch (event) {
+       case CPUFREQ_GOV_START:
+               if ((!cpu_online(cpu)) || (!policy->cur))
+                       return -EINVAL;
+
+               mutex_lock(&dbs_data->mutex);
+
+               dbs_data->enable++;
+               cpu_cdbs->cpu = cpu;
+               for_each_cpu(j, policy->cpus) {
+                       struct cpu_dbs_common_info *j_cdbs;
+                       j_cdbs = dbs_data->get_cpu_cdbs(j);
+
+                       j_cdbs->cur_policy = policy;
+                       j_cdbs->prev_cpu_idle = get_cpu_idle_time(j,
+                                       &j_cdbs->prev_cpu_wall);
+                       if (ignore_nice)
+                               j_cdbs->prev_cpu_nice =
+                                       kcpustat_cpu(j).cpustat[CPUTIME_NICE];
+               }
+
+               /*
+                * Start the timerschedule work, when this governor is used for
+                * first time
+                */
+               if (dbs_data->enable != 1)
+                       goto second_time;
+
+               rc = sysfs_create_group(cpufreq_global_kobject,
+                               dbs_data->attr_group);
+               if (rc) {
+                       mutex_unlock(&dbs_data->mutex);
+                       return rc;
+               }
+
+               /* policy latency is in nS. Convert it to uS first */
+               latency = policy->cpuinfo.transition_latency / 1000;
+               if (latency == 0)
+                       latency = 1;
+
+               /*
+                * conservative does not implement micro like ondemand
+                * governor, thus we are bound to jiffes/HZ
+                */
+               if (dbs_data->governor == GOV_CONSERVATIVE) {
+                       struct cs_ops *ops = dbs_data->gov_ops;
+
+                       cpufreq_register_notifier(ops->notifier_block,
+                                       CPUFREQ_TRANSITION_NOTIFIER);
+
+                       dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO *
+                               jiffies_to_usecs(10);
+               } else {
+                       struct od_ops *ops = dbs_data->gov_ops;
+
+                       od_tuners->io_is_busy = ops->io_busy();
+               }
+
+               /* Bring kernel and HW constraints together */
+               dbs_data->min_sampling_rate = max(dbs_data->min_sampling_rate,
+                               MIN_LATENCY_MULTIPLIER * latency);
+               *sampling_rate = max(dbs_data->min_sampling_rate, latency *
+                               LATENCY_MULTIPLIER);
+
+second_time:
+               if (dbs_data->governor == GOV_CONSERVATIVE) {
+                       cs_dbs_info->down_skip = 0;
+                       cs_dbs_info->enable = 1;
+                       cs_dbs_info->requested_freq = policy->cur;
+               } else {
+                       struct od_ops *ops = dbs_data->gov_ops;
+                       od_dbs_info->rate_mult = 1;
+                       od_dbs_info->sample_type = OD_NORMAL_SAMPLE;
+                       ops->powersave_bias_init_cpu(cpu);
+               }
+               mutex_unlock(&dbs_data->mutex);
+
+               mutex_init(&cpu_cdbs->timer_mutex);
+               dbs_timer_init(dbs_data, cpu_cdbs, *sampling_rate);
+               break;
+
+       case CPUFREQ_GOV_STOP:
+               if (dbs_data->governor == GOV_CONSERVATIVE)
+                       cs_dbs_info->enable = 0;
+
+               dbs_timer_exit(cpu_cdbs);
+
+               mutex_lock(&dbs_data->mutex);
+               mutex_destroy(&cpu_cdbs->timer_mutex);
+               dbs_data->enable--;
+               if (!dbs_data->enable) {
+                       struct cs_ops *ops = dbs_data->gov_ops;
+
+                       sysfs_remove_group(cpufreq_global_kobject,
+                                       dbs_data->attr_group);
+                       if (dbs_data->governor == GOV_CONSERVATIVE)
+                               cpufreq_unregister_notifier(ops->notifier_block,
+                                               CPUFREQ_TRANSITION_NOTIFIER);
+               }
+               mutex_unlock(&dbs_data->mutex);
+
+               break;
+
+       case CPUFREQ_GOV_LIMITS:
+               mutex_lock(&cpu_cdbs->timer_mutex);
+               if (policy->max < cpu_cdbs->cur_policy->cur)
+                       __cpufreq_driver_target(cpu_cdbs->cur_policy,
+                                       policy->max, CPUFREQ_RELATION_H);
+               else if (policy->min > cpu_cdbs->cur_policy->cur)
+                       __cpufreq_driver_target(cpu_cdbs->cur_policy,
+                                       policy->min, CPUFREQ_RELATION_L);
+               dbs_check_cpu(dbs_data, cpu);
+               mutex_unlock(&cpu_cdbs->timer_mutex);
+               break;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(cpufreq_governor_dbs);
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h
new file mode 100644 (file)
index 0000000..f661654
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * drivers/cpufreq/cpufreq_governor.h
+ *
+ * Header file for CPUFreq governors common code
+ *
+ * Copyright   (C) 2001 Russell King
+ *             (C) 2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>.
+ *             (C) 2003 Jun Nakajima <jun.nakajima@intel.com>
+ *             (C) 2009 Alexander Clouter <alex@digriz.org.uk>
+ *             (c) 2012 Viresh Kumar <viresh.kumar@linaro.org>
+ *
+ * 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 _CPUFREQ_GOVERNER_H
+#define _CPUFREQ_GOVERNER_H
+
+#include <linux/cpufreq.h>
+#include <linux/kobject.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include <linux/sysfs.h>
+
+/*
+ * The polling frequency depends on the capability of the processor. Default
+ * polling frequency is 1000 times the transition latency of the processor. The
+ * governor will work on any processor with transition latency <= 10mS, using
+ * appropriate sampling rate.
+ *
+ * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL)
+ * this governor will not work. All times here are in uS.
+ */
+#define MIN_SAMPLING_RATE_RATIO                        (2)
+#define LATENCY_MULTIPLIER                     (1000)
+#define MIN_LATENCY_MULTIPLIER                 (100)
+#define TRANSITION_LATENCY_LIMIT               (10 * 1000 * 1000)
+
+/* Ondemand Sampling types */
+enum {OD_NORMAL_SAMPLE, OD_SUB_SAMPLE};
+
+/* Macro creating sysfs show routines */
+#define show_one(_gov, file_name, object)                              \
+static ssize_t show_##file_name                                                \
+(struct kobject *kobj, struct attribute *attr, char *buf)              \
+{                                                                      \
+       return sprintf(buf, "%u\n", _gov##_tuners.object);              \
+}
+
+#define define_get_cpu_dbs_routines(_dbs_info)                         \
+static struct cpu_dbs_common_info *get_cpu_cdbs(int cpu)               \
+{                                                                      \
+       return &per_cpu(_dbs_info, cpu).cdbs;                           \
+}                                                                      \
+                                                                       \
+static void *get_cpu_dbs_info_s(int cpu)                               \
+{                                                                      \
+       return &per_cpu(_dbs_info, cpu);                                \
+}
+
+/*
+ * Abbreviations:
+ * dbs: used as a shortform for demand based switching It helps to keep variable
+ *     names smaller, simpler
+ * cdbs: common dbs
+ * on_*: On-demand governor
+ * cs_*: Conservative governor
+ */
+
+/* Per cpu structures */
+struct cpu_dbs_common_info {
+       int cpu;
+       u64 prev_cpu_idle;
+       u64 prev_cpu_wall;
+       u64 prev_cpu_nice;
+       struct cpufreq_policy *cur_policy;
+       struct delayed_work work;
+       /*
+        * percpu mutex that serializes governor limit change with gov_dbs_timer
+        * invocation. We do not want gov_dbs_timer to run when user is changing
+        * the governor or limits.
+        */
+       struct mutex timer_mutex;
+};
+
+struct od_cpu_dbs_info_s {
+       struct cpu_dbs_common_info cdbs;
+       u64 prev_cpu_iowait;
+       struct cpufreq_frequency_table *freq_table;
+       unsigned int freq_lo;
+       unsigned int freq_lo_jiffies;
+       unsigned int freq_hi_jiffies;
+       unsigned int rate_mult;
+       unsigned int sample_type:1;
+};
+
+struct cs_cpu_dbs_info_s {
+       struct cpu_dbs_common_info cdbs;
+       unsigned int down_skip;
+       unsigned int requested_freq;
+       unsigned int enable:1;
+};
+
+/* Governers sysfs tunables */
+struct od_dbs_tuners {
+       unsigned int ignore_nice;
+       unsigned int sampling_rate;
+       unsigned int sampling_down_factor;
+       unsigned int up_threshold;
+       unsigned int down_differential;
+       unsigned int powersave_bias;
+       unsigned int io_is_busy;
+};
+
+struct cs_dbs_tuners {
+       unsigned int ignore_nice;
+       unsigned int sampling_rate;
+       unsigned int sampling_down_factor;
+       unsigned int up_threshold;
+       unsigned int down_threshold;
+       unsigned int freq_step;
+};
+
+/* Per Governer data */
+struct dbs_data {
+       /* Common across governors */
+       #define GOV_ONDEMAND            0
+       #define GOV_CONSERVATIVE        1
+       int governor;
+       unsigned int min_sampling_rate;
+       unsigned int enable; /* number of CPUs using this policy */
+       struct attribute_group *attr_group;
+       void *tuners;
+
+       /* dbs_mutex protects dbs_enable in governor start/stop */
+       struct mutex mutex;
+
+       struct cpu_dbs_common_info *(*get_cpu_cdbs)(int cpu);
+       void *(*get_cpu_dbs_info_s)(int cpu);
+       void (*gov_dbs_timer)(struct work_struct *work);
+       void (*gov_check_cpu)(int cpu, unsigned int load);
+
+       /* Governor specific ops, see below */
+       void *gov_ops;
+};
+
+/* Governor specific ops, will be passed to dbs_data->gov_ops */
+struct od_ops {
+       int (*io_busy)(void);
+       void (*powersave_bias_init_cpu)(int cpu);
+       unsigned int (*powersave_bias_target)(struct cpufreq_policy *policy,
+                       unsigned int freq_next, unsigned int relation);
+       void (*freq_increase)(struct cpufreq_policy *p, unsigned int freq);
+};
+
+struct cs_ops {
+       struct notifier_block *notifier_block;
+};
+
+static inline int delay_for_sampling_rate(unsigned int sampling_rate)
+{
+       int delay = usecs_to_jiffies(sampling_rate);
+
+       /* We want all CPUs to do sampling nearly on same jiffy */
+       if (num_online_cpus() > 1)
+               delay -= jiffies % delay;
+
+       return delay;
+}
+
+u64 get_cpu_idle_time(unsigned int cpu, u64 *wall);
+void dbs_check_cpu(struct dbs_data *dbs_data, int cpu);
+int cpufreq_governor_dbs(struct dbs_data *dbs_data,
+               struct cpufreq_policy *policy, unsigned int event);
+#endif /* _CPUFREQ_GOVERNER_H */
index 396322f..7731f7c 100644 (file)
  * published by the Free Software Foundation.
  */
 
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/cpufreq.h>
-#include <linux/cpu.h>
-#include <linux/jiffies.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/kernel_stat.h>
+#include <linux/kobject.h>
+#include <linux/module.h>
 #include <linux/mutex.h>
-#include <linux/hrtimer.h>
+#include <linux/percpu-defs.h>
+#include <linux/sysfs.h>
 #include <linux/tick.h>
-#include <linux/ktime.h>
-#include <linux/sched.h>
+#include <linux/types.h>
 
-/*
- * dbs is used in this file as a shortform for demandbased switching
- * It helps to keep variable names smaller, simpler
- */
+#include "cpufreq_governor.h"
 
+/* On-demand governor macors */
 #define DEF_FREQUENCY_DOWN_DIFFERENTIAL                (10)
 #define DEF_FREQUENCY_UP_THRESHOLD             (80)
 #define DEF_SAMPLING_DOWN_FACTOR               (1)
 #define MIN_FREQUENCY_UP_THRESHOLD             (11)
 #define MAX_FREQUENCY_UP_THRESHOLD             (100)
 
-/*
- * The polling frequency of this governor depends on the capability of
- * the processor. Default polling frequency is 1000 times the transition
- * latency of the processor. The governor will work on any processor with
- * transition latency <= 10mS, using appropriate sampling
- * rate.
- * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL)
- * this governor will not work.
- * All times here are in uS.
- */
-#define MIN_SAMPLING_RATE_RATIO                        (2)
-
-static unsigned int min_sampling_rate;
-
-#define LATENCY_MULTIPLIER                     (1000)
-#define MIN_LATENCY_MULTIPLIER                 (100)
-#define TRANSITION_LATENCY_LIMIT               (10 * 1000 * 1000)
-
-static void do_dbs_timer(struct work_struct *work);
-static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
-                               unsigned int event);
+static struct dbs_data od_dbs_data;
+static DEFINE_PER_CPU(struct od_cpu_dbs_info_s, od_cpu_dbs_info);
 
 #ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND
-static
+static struct cpufreq_governor cpufreq_gov_ondemand;
 #endif
-struct cpufreq_governor cpufreq_gov_ondemand = {
-       .name                   = "ondemand",
-       .governor               = cpufreq_governor_dbs,
-       .max_transition_latency = TRANSITION_LATENCY_LIMIT,
-       .owner                  = THIS_MODULE,
-};
 
-/* Sampling types */
-enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE};
-
-struct cpu_dbs_info_s {
-       cputime64_t prev_cpu_idle;
-       cputime64_t prev_cpu_iowait;
-       cputime64_t prev_cpu_wall;
-       cputime64_t prev_cpu_nice;
-       struct cpufreq_policy *cur_policy;
-       struct delayed_work work;
-       struct cpufreq_frequency_table *freq_table;
-       unsigned int freq_lo;
-       unsigned int freq_lo_jiffies;
-       unsigned int freq_hi_jiffies;
-       unsigned int rate_mult;
-       int cpu;
-       unsigned int sample_type:1;
-       /*
-        * percpu mutex that serializes governor limit change with
-        * do_dbs_timer invocation. We do not want do_dbs_timer to run
-        * when user is changing the governor or limits.
-        */
-       struct mutex timer_mutex;
-};
-static DEFINE_PER_CPU(struct cpu_dbs_info_s, od_cpu_dbs_info);
-
-static unsigned int dbs_enable;        /* number of CPUs using this policy */
-
-/*
- * dbs_mutex protects dbs_enable in governor start/stop.
- */
-static DEFINE_MUTEX(dbs_mutex);
-
-static struct dbs_tuners {
-       unsigned int sampling_rate;
-       unsigned int up_threshold;
-       unsigned int down_differential;
-       unsigned int ignore_nice;
-       unsigned int sampling_down_factor;
-       unsigned int powersave_bias;
-       unsigned int io_is_busy;
-} dbs_tuners_ins = {
+static struct od_dbs_tuners od_tuners = {
        .up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
        .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
        .down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL,
@@ -119,48 +52,35 @@ 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)
+static void ondemand_powersave_bias_init_cpu(int cpu)
 {
-       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);
+       struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
 
-       return idle_time;
+       dbs_info->freq_table = cpufreq_frequency_get_table(cpu);
+       dbs_info->freq_lo = 0;
 }
 
-static inline cputime64_t get_cpu_iowait_time(unsigned int cpu, cputime64_t *wall)
+/*
+ * Not all CPUs want IO time to be accounted as busy; this depends on how
+ * efficient idling at a higher frequency/voltage is.
+ * Pavel Machek says this is not so for various generations of AMD and old
+ * Intel systems.
+ * Mike Chan (androidlcom) calis this is also not true for ARM.
+ * Because of this, whitelist specific known (series) of CPUs by default, and
+ * leave all others up to the user.
+ */
+static int should_io_be_busy(void)
 {
-       u64 iowait_time = get_cpu_iowait_time_us(cpu, wall);
-
-       if (iowait_time == -1ULL)
-               return 0;
-
-       return iowait_time;
+#if defined(CONFIG_X86)
+       /*
+        * For Intel, Core 2 (model 15) andl later have an efficient idle.
+        */
+       if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
+                       boot_cpu_data.x86 == 6 &&
+                       boot_cpu_data.x86_model >= 15)
+               return 1;
+#endif
+       return 0;
 }
 
 /*
@@ -169,14 +89,13 @@ static inline cputime64_t get_cpu_iowait_time(unsigned int cpu, cputime64_t *wal
  * freq_lo, and freq_lo_jiffies in percpu area for averaging freqs.
  */
 static unsigned int powersave_bias_target(struct cpufreq_policy *policy,
-                                         unsigned int freq_next,
-                                         unsigned int relation)
+               unsigned int freq_next, unsigned int relation)
 {
        unsigned int freq_req, freq_reduc, freq_avg;
        unsigned int freq_hi, freq_lo;
        unsigned int index = 0;
        unsigned int jiffies_total, jiffies_hi, jiffies_lo;
-       struct cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info,
+       struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info,
                                                   policy->cpu);
 
        if (!dbs_info->freq_table) {
@@ -188,7 +107,7 @@ static unsigned int powersave_bias_target(struct cpufreq_policy *policy,
        cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_next,
                        relation, &index);
        freq_req = dbs_info->freq_table[index].frequency;
-       freq_reduc = freq_req * dbs_tuners_ins.powersave_bias / 1000;
+       freq_reduc = freq_req * od_tuners.powersave_bias / 1000;
        freq_avg = freq_req - freq_reduc;
 
        /* Find freq bounds for freq_avg in freq_table */
@@ -207,7 +126,7 @@ static unsigned int powersave_bias_target(struct cpufreq_policy *policy,
                dbs_info->freq_lo_jiffies = 0;
                return freq_lo;
        }
-       jiffies_total = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
+       jiffies_total = usecs_to_jiffies(od_tuners.sampling_rate);
        jiffies_hi = (freq_avg - freq_lo) * jiffies_total;
        jiffies_hi += ((freq_hi - freq_lo) / 2);
        jiffies_hi /= (freq_hi - freq_lo);
@@ -218,13 +137,6 @@ static unsigned int powersave_bias_target(struct cpufreq_policy *policy,
        return freq_hi;
 }
 
-static void ondemand_powersave_bias_init_cpu(int cpu)
-{
-       struct cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
-       dbs_info->freq_table = cpufreq_frequency_get_table(cpu);
-       dbs_info->freq_lo = 0;
-}
-
 static void ondemand_powersave_bias_init(void)
 {
        int i;
@@ -233,83 +145,173 @@ static void ondemand_powersave_bias_init(void)
        }
 }
 
-/************************** sysfs interface ************************/
+static void dbs_freq_increase(struct cpufreq_policy *p, unsigned int freq)
+{
+       if (od_tuners.powersave_bias)
+               freq = powersave_bias_target(p, freq, CPUFREQ_RELATION_H);
+       else if (p->cur == p->max)
+               return;
 
-static ssize_t show_sampling_rate_min(struct kobject *kobj,
-                                     struct attribute *attr, char *buf)
+       __cpufreq_driver_target(p, freq, od_tuners.powersave_bias ?
+                       CPUFREQ_RELATION_L : CPUFREQ_RELATION_H);
+}
+
+/*
+ * Every sampling_rate, we check, if current idle time is less than 20%
+ * (default), then we try to increase frequency Every sampling_rate, we look for
+ * a the lowest frequency which can sustain the load while keeping idle time
+ * over 30%. If such a frequency exist, we try to decrease to this frequency.
+ *
+ * Any frequency increase takes it to the maximum frequency. Frequency reduction
+ * happens at minimum steps of 5% (default) of current frequency
+ */
+static void od_check_cpu(int cpu, unsigned int load_freq)
 {
-       return sprintf(buf, "%u\n", min_sampling_rate);
+       struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
+       struct cpufreq_policy *policy = dbs_info->cdbs.cur_policy;
+
+       dbs_info->freq_lo = 0;
+
+       /* Check for frequency increase */
+       if (load_freq > od_tuners.up_threshold * policy->cur) {
+               /* If switching to max speed, apply sampling_down_factor */
+               if (policy->cur < policy->max)
+                       dbs_info->rate_mult =
+                               od_tuners.sampling_down_factor;
+               dbs_freq_increase(policy, policy->max);
+               return;
+       }
+
+       /* Check for frequency decrease */
+       /* if we cannot reduce the frequency anymore, break out early */
+       if (policy->cur == policy->min)
+               return;
+
+       /*
+        * The optimal frequency is the frequency that is the lowest that can
+        * support the current CPU usage without triggering the up policy. To be
+        * safe, we focus 10 points under the threshold.
+        */
+       if (load_freq < (od_tuners.up_threshold - od_tuners.down_differential) *
+                       policy->cur) {
+               unsigned int freq_next;
+               freq_next = load_freq / (od_tuners.up_threshold -
+                               od_tuners.down_differential);
+
+               /* No longer fully busy, reset rate_mult */
+               dbs_info->rate_mult = 1;
+
+               if (freq_next < policy->min)
+                       freq_next = policy->min;
+
+               if (!od_tuners.powersave_bias) {
+                       __cpufreq_driver_target(policy, freq_next,
+                                       CPUFREQ_RELATION_L);
+               } else {
+                       int freq = powersave_bias_target(policy, freq_next,
+                                       CPUFREQ_RELATION_L);
+                       __cpufreq_driver_target(policy, freq,
+                                       CPUFREQ_RELATION_L);
+               }
+       }
 }
 
-define_one_global_ro(sampling_rate_min);
+static void od_dbs_timer(struct work_struct *work)
+{
+       struct od_cpu_dbs_info_s *dbs_info =
+               container_of(work, struct od_cpu_dbs_info_s, cdbs.work.work);
+       unsigned int cpu = dbs_info->cdbs.cpu;
+       int delay, sample_type = dbs_info->sample_type;
+
+       mutex_lock(&dbs_info->cdbs.timer_mutex);
+
+       /* Common NORMAL_SAMPLE setup */
+       dbs_info->sample_type = OD_NORMAL_SAMPLE;
+       if (sample_type == OD_SUB_SAMPLE) {
+               delay = dbs_info->freq_lo_jiffies;
+               __cpufreq_driver_target(dbs_info->cdbs.cur_policy,
+                       dbs_info->freq_lo, CPUFREQ_RELATION_H);
+       } else {
+               dbs_check_cpu(&od_dbs_data, cpu);
+               if (dbs_info->freq_lo) {
+                       /* Setup timer for SUB_SAMPLE */
+                       dbs_info->sample_type = OD_SUB_SAMPLE;
+                       delay = dbs_info->freq_hi_jiffies;
+               } else {
+                       delay = delay_for_sampling_rate(od_tuners.sampling_rate
+                                               * dbs_info->rate_mult);
+               }
+       }
+
+       schedule_delayed_work_on(cpu, &dbs_info->cdbs.work, delay);
+       mutex_unlock(&dbs_info->cdbs.timer_mutex);
+}
+
+/************************** sysfs interface ************************/
 
-/* cpufreq_ondemand Governor Tunables */
-#define show_one(file_name, object)                                    \
-static ssize_t show_##file_name                                                \
-(struct kobject *kobj, struct attribute *attr, char *buf)              \
-{                                                                      \
-       return sprintf(buf, "%u\n", dbs_tuners_ins.object);             \
+static ssize_t show_sampling_rate_min(struct kobject *kobj,
+                                     struct attribute *attr, char *buf)
+{
+       return sprintf(buf, "%u\n", od_dbs_data.min_sampling_rate);
 }
-show_one(sampling_rate, sampling_rate);
-show_one(io_is_busy, io_is_busy);
-show_one(up_threshold, up_threshold);
-show_one(sampling_down_factor, sampling_down_factor);
-show_one(ignore_nice_load, ignore_nice);
-show_one(powersave_bias, powersave_bias);
 
 /**
  * update_sampling_rate - update sampling rate effective immediately if needed.
  * @new_rate: new sampling rate
  *
  * If new rate is smaller than the old, simply updaing
- * dbs_tuners_int.sampling_rate might not be appropriate. For example,
- * if the original sampling_rate was 1 second and the requested new sampling
- * rate is 10 ms because the user needs immediate reaction from ondemand
- * governor, but not sure if higher frequency will be required or not,
- * then, the governor may change the sampling rate too late; up to 1 second
- * later. Thus, if we are reducing the sampling rate, we need to make the
- * new value effective immediately.
+ * dbs_tuners_int.sampling_rate might not be appropriate. For example, if the
+ * original sampling_rate was 1 second and the requested new sampling rate is 10
+ * ms because the user needs immediate reaction from ondemand governor, but not
+ * sure if higher frequency will be required or not, then, the governor may
+ * change the sampling rate too late; up to 1 second later. Thus, if we are
+ * reducing the sampling rate, we need to make the new value effective
+ * immediately.
  */
 static void update_sampling_rate(unsigned int new_rate)
 {
        int cpu;
 
-       dbs_tuners_ins.sampling_rate = new_rate
-                                    = max(new_rate, min_sampling_rate);
+       od_tuners.sampling_rate = new_rate = max(new_rate,
+                       od_dbs_data.min_sampling_rate);
 
        for_each_online_cpu(cpu) {
                struct cpufreq_policy *policy;
-               struct cpu_dbs_info_s *dbs_info;
+               struct od_cpu_dbs_info_s *dbs_info;
                unsigned long next_sampling, appointed_at;
 
                policy = cpufreq_cpu_get(cpu);
                if (!policy)
                        continue;
+               if (policy->governor != &cpufreq_gov_ondemand) {
+                       cpufreq_cpu_put(policy);
+                       continue;
+               }
                dbs_info = &per_cpu(od_cpu_dbs_info, policy->cpu);
                cpufreq_cpu_put(policy);
 
-               mutex_lock(&dbs_info->timer_mutex);
+               mutex_lock(&dbs_info->cdbs.timer_mutex);
 
-               if (!delayed_work_pending(&dbs_info->work)) {
-                       mutex_unlock(&dbs_info->timer_mutex);
+               if (!delayed_work_pending(&dbs_info->cdbs.work)) {
+                       mutex_unlock(&dbs_info->cdbs.timer_mutex);
                        continue;
                }
 
-               next_sampling  = jiffies + usecs_to_jiffies(new_rate);
-               appointed_at = dbs_info->work.timer.expires;
-
+               next_sampling = jiffies + usecs_to_jiffies(new_rate);
+               appointed_at = dbs_info->cdbs.work.timer.expires;
 
                if (time_before(next_sampling, appointed_at)) {
 
-                       mutex_unlock(&dbs_info->timer_mutex);
-                       cancel_delayed_work_sync(&dbs_info->work);
-                       mutex_lock(&dbs_info->timer_mutex);
+                       mutex_unlock(&dbs_info->cdbs.timer_mutex);
+                       cancel_delayed_work_sync(&dbs_info->cdbs.work);
+                       mutex_lock(&dbs_info->cdbs.timer_mutex);
 
-                       schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work,
-                                                usecs_to_jiffies(new_rate));
+                       schedule_delayed_work_on(dbs_info->cdbs.cpu,
+                                       &dbs_info->cdbs.work,
+                                       usecs_to_jiffies(new_rate));
 
                }
-               mutex_unlock(&dbs_info->timer_mutex);
+               mutex_unlock(&dbs_info->cdbs.timer_mutex);
        }
 }
 
@@ -334,7 +336,7 @@ static ssize_t store_io_is_busy(struct kobject *a, struct attribute *b,
        ret = sscanf(buf, "%u", &input);
        if (ret != 1)
                return -EINVAL;
-       dbs_tuners_ins.io_is_busy = !!input;
+       od_tuners.io_is_busy = !!input;
        return count;
 }
 
@@ -349,7 +351,7 @@ static ssize_t store_up_threshold(struct kobject *a, struct attribute *b,
                        input < MIN_FREQUENCY_UP_THRESHOLD) {
                return -EINVAL;
        }
-       dbs_tuners_ins.up_threshold = input;
+       od_tuners.up_threshold = input;
        return count;
 }
 
@@ -362,12 +364,12 @@ static ssize_t store_sampling_down_factor(struct kobject *a,
 
        if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
                return -EINVAL;
-       dbs_tuners_ins.sampling_down_factor = input;
+       od_tuners.sampling_down_factor = input;
 
        /* Reset down sampling multiplier in case it was active */
        for_each_online_cpu(j) {
-               struct cpu_dbs_info_s *dbs_info;
-               dbs_info = &per_cpu(od_cpu_dbs_info, j);
+               struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info,
+                               j);
                dbs_info->rate_mult = 1;
        }
        return count;
@@ -388,19 +390,20 @@ static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
        if (input > 1)
                input = 1;
 
-       if (input == dbs_tuners_ins.ignore_nice) { /* nothing to do */
+       if (input == od_tuners.ignore_nice) { /* nothing to do */
                return count;
        }
-       dbs_tuners_ins.ignore_nice = input;
+       od_tuners.ignore_nice = input;
 
        /* we need to re-evaluate prev_cpu_idle */
        for_each_online_cpu(j) {
-               struct cpu_dbs_info_s *dbs_info;
+               struct od_cpu_dbs_info_s *dbs_info;
                dbs_info = &per_cpu(od_cpu_dbs_info, j);
-               dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
-                                               &dbs_info->prev_cpu_wall);
-               if (dbs_tuners_ins.ignore_nice)
-                       dbs_info->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE];
+               dbs_info->cdbs.prev_cpu_idle = get_cpu_idle_time(j,
+                                               &dbs_info->cdbs.prev_cpu_wall);
+               if (od_tuners.ignore_nice)
+                       dbs_info->cdbs.prev_cpu_nice =
+                               kcpustat_cpu(j).cpustat[CPUTIME_NICE];
 
        }
        return count;
@@ -419,17 +422,25 @@ static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b,
        if (input > 1000)
                input = 1000;
 
-       dbs_tuners_ins.powersave_bias = input;
+       od_tuners.powersave_bias = input;
        ondemand_powersave_bias_init();
        return count;
 }
 
+show_one(od, sampling_rate, sampling_rate);
+show_one(od, io_is_busy, io_is_busy);
+show_one(od, up_threshold, up_threshold);
+show_one(od, sampling_down_factor, sampling_down_factor);
+show_one(od, ignore_nice_load, ignore_nice);
+show_one(od, powersave_bias, powersave_bias);
+
 define_one_global_rw(sampling_rate);
 define_one_global_rw(io_is_busy);
 define_one_global_rw(up_threshold);
 define_one_global_rw(sampling_down_factor);
 define_one_global_rw(ignore_nice_load);
 define_one_global_rw(powersave_bias);
+define_one_global_ro(sampling_rate_min);
 
 static struct attribute *dbs_attributes[] = {
        &sampling_rate_min.attr,
@@ -442,354 +453,71 @@ static struct attribute *dbs_attributes[] = {
        NULL
 };
 
-static struct attribute_group dbs_attr_group = {
+static struct attribute_group od_attr_group = {
        .attrs = dbs_attributes,
        .name = "ondemand",
 };
 
 /************************** sysfs end ************************/
 
-static void dbs_freq_increase(struct cpufreq_policy *p, unsigned int freq)
-{
-       if (dbs_tuners_ins.powersave_bias)
-               freq = powersave_bias_target(p, freq, CPUFREQ_RELATION_H);
-       else if (p->cur == p->max)
-               return;
-
-       __cpufreq_driver_target(p, freq, dbs_tuners_ins.powersave_bias ?
-                       CPUFREQ_RELATION_L : CPUFREQ_RELATION_H);
-}
-
-static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
-{
-       unsigned int max_load_freq;
-
-       struct cpufreq_policy *policy;
-       unsigned int j;
-
-       this_dbs_info->freq_lo = 0;
-       policy = this_dbs_info->cur_policy;
-
-       /*
-        * Every sampling_rate, we check, if current idle time is less
-        * than 20% (default), then we try to increase frequency
-        * Every sampling_rate, we look for a the lowest
-        * frequency which can sustain the load while keeping idle time over
-        * 30%. If such a frequency exist, we try to decrease to this frequency.
-        *
-        * Any frequency increase takes it to the maximum frequency.
-        * Frequency reduction happens at minimum steps of
-        * 5% (default) of current frequency
-        */
-
-       /* Get Absolute Load - in terms of freq */
-       max_load_freq = 0;
-
-       for_each_cpu(j, policy->cpus) {
-               struct cpu_dbs_info_s *j_dbs_info;
-               cputime64_t cur_wall_time, cur_idle_time, cur_iowait_time;
-               unsigned int idle_time, wall_time, iowait_time;
-               unsigned int load, load_freq;
-               int freq_avg;
-
-               j_dbs_info = &per_cpu(od_cpu_dbs_info, j);
-
-               cur_idle_time = get_cpu_idle_time(j, &cur_wall_time);
-               cur_iowait_time = get_cpu_iowait_time(j, &cur_wall_time);
-
-               wall_time = (unsigned int)
-                       (cur_wall_time - j_dbs_info->prev_cpu_wall);
-               j_dbs_info->prev_cpu_wall = cur_wall_time;
-
-               idle_time = (unsigned int)
-                       (cur_idle_time - j_dbs_info->prev_cpu_idle);
-               j_dbs_info->prev_cpu_idle = cur_idle_time;
-
-               iowait_time = (unsigned int)
-                       (cur_iowait_time - j_dbs_info->prev_cpu_iowait);
-               j_dbs_info->prev_cpu_iowait = cur_iowait_time;
-
-               if (dbs_tuners_ins.ignore_nice) {
-                       u64 cur_nice;
-                       unsigned long cur_nice_jiffies;
-
-                       cur_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE] -
-                                        j_dbs_info->prev_cpu_nice;
-                       /*
-                        * Assumption: nice time between sampling periods will
-                        * be less than 2^32 jiffies for 32 bit sys
-                        */
-                       cur_nice_jiffies = (unsigned long)
-                                       cputime64_to_jiffies64(cur_nice);
-
-                       j_dbs_info->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE];
-                       idle_time += jiffies_to_usecs(cur_nice_jiffies);
-               }
-
-               /*
-                * For the purpose of ondemand, waiting for disk IO is an
-                * indication that you're performance critical, and not that
-                * the system is actually idle. So subtract the iowait time
-                * from the cpu idle time.
-                */
-
-               if (dbs_tuners_ins.io_is_busy && idle_time >= iowait_time)
-                       idle_time -= iowait_time;
-
-               if (unlikely(!wall_time || wall_time < idle_time))
-                       continue;
-
-               load = 100 * (wall_time - idle_time) / wall_time;
-
-               freq_avg = __cpufreq_driver_getavg(policy, j);
-               if (freq_avg <= 0)
-                       freq_avg = policy->cur;
-
-               load_freq = load * freq_avg;
-               if (load_freq > max_load_freq)
-                       max_load_freq = load_freq;
-       }
+define_get_cpu_dbs_routines(od_cpu_dbs_info);
 
-       /* Check for frequency increase */
-       if (max_load_freq > dbs_tuners_ins.up_threshold * policy->cur) {
-               /* If switching to max speed, apply sampling_down_factor */
-               if (policy->cur < policy->max)
-                       this_dbs_info->rate_mult =
-                               dbs_tuners_ins.sampling_down_factor;
-               dbs_freq_increase(policy, policy->max);
-               return;
-       }
-
-       /* Check for frequency decrease */
-       /* if we cannot reduce the frequency anymore, break out early */
-       if (policy->cur == policy->min)
-               return;
-
-       /*
-        * The optimal frequency is the frequency that is the lowest that
-        * can support the current CPU usage without triggering the up
-        * policy. To be safe, we focus 10 points under the threshold.
-        */
-       if (max_load_freq <
-           (dbs_tuners_ins.up_threshold - dbs_tuners_ins.down_differential) *
-            policy->cur) {
-               unsigned int freq_next;
-               freq_next = max_load_freq /
-                               (dbs_tuners_ins.up_threshold -
-                                dbs_tuners_ins.down_differential);
-
-               /* No longer fully busy, reset rate_mult */
-               this_dbs_info->rate_mult = 1;
-
-               if (freq_next < policy->min)
-                       freq_next = policy->min;
-
-               if (!dbs_tuners_ins.powersave_bias) {
-                       __cpufreq_driver_target(policy, freq_next,
-                                       CPUFREQ_RELATION_L);
-               } else {
-                       int freq = powersave_bias_target(policy, freq_next,
-                                       CPUFREQ_RELATION_L);
-                       __cpufreq_driver_target(policy, freq,
-                               CPUFREQ_RELATION_L);
-               }
-       }
-}
-
-static void do_dbs_timer(struct work_struct *work)
-{
-       struct cpu_dbs_info_s *dbs_info =
-               container_of(work, struct cpu_dbs_info_s, work.work);
-       unsigned int cpu = dbs_info->cpu;
-       int sample_type = dbs_info->sample_type;
-
-       int delay;
-
-       mutex_lock(&dbs_info->timer_mutex);
-
-       /* Common NORMAL_SAMPLE setup */
-       dbs_info->sample_type = DBS_NORMAL_SAMPLE;
-       if (!dbs_tuners_ins.powersave_bias ||
-           sample_type == DBS_NORMAL_SAMPLE) {
-               dbs_check_cpu(dbs_info);
-               if (dbs_info->freq_lo) {
-                       /* Setup timer for SUB_SAMPLE */
-                       dbs_info->sample_type = DBS_SUB_SAMPLE;
-                       delay = dbs_info->freq_hi_jiffies;
-               } else {
-                       /* We want all CPUs to do sampling nearly on
-                        * same jiffy
-                        */
-                       delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate
-                               * dbs_info->rate_mult);
-
-                       if (num_online_cpus() > 1)
-                               delay -= jiffies % delay;
-               }
-       } else {
-               __cpufreq_driver_target(dbs_info->cur_policy,
-                       dbs_info->freq_lo, CPUFREQ_RELATION_H);
-               delay = dbs_info->freq_lo_jiffies;
-       }
-       schedule_delayed_work_on(cpu, &dbs_info->work, delay);
-       mutex_unlock(&dbs_info->timer_mutex);
-}
-
-static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
-{
-       /* We want all CPUs to do sampling nearly on same jiffy */
-       int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
-
-       if (num_online_cpus() > 1)
-               delay -= jiffies % delay;
+static struct od_ops od_ops = {
+       .io_busy = should_io_be_busy,
+       .powersave_bias_init_cpu = ondemand_powersave_bias_init_cpu,
+       .powersave_bias_target = powersave_bias_target,
+       .freq_increase = dbs_freq_increase,
+};
 
-       dbs_info->sample_type = DBS_NORMAL_SAMPLE;
-       INIT_DEFERRABLE_WORK(&dbs_info->work, do_dbs_timer);
-       schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work, delay);
-}
+static struct dbs_data od_dbs_data = {
+       .governor = GOV_ONDEMAND,
+       .attr_group = &od_attr_group,
+       .tuners = &od_tuners,
+       .get_cpu_cdbs = get_cpu_cdbs,
+       .get_cpu_dbs_info_s = get_cpu_dbs_info_s,
+       .gov_dbs_timer = od_dbs_timer,
+       .gov_check_cpu = od_check_cpu,
+       .gov_ops = &od_ops,
+};
 
-static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
+static int od_cpufreq_governor_dbs(struct cpufreq_policy *policy,
+               unsigned int event)
 {
-       cancel_delayed_work_sync(&dbs_info->work);
+       return cpufreq_governor_dbs(&od_dbs_data, policy, event);
 }
 
-/*
- * Not all CPUs want IO time to be accounted as busy; this dependson how
- * efficient idling at a higher frequency/voltage is.
- * Pavel Machek says this is not so for various generations of AMD and old
- * Intel systems.
- * Mike Chan (androidlcom) calis this is also not true for ARM.
- * Because of this, whitelist specific known (series) of CPUs by default, and
- * leave all others up to the user.
- */
-static int should_io_be_busy(void)
-{
-#if defined(CONFIG_X86)
-       /*
-        * For Intel, Core 2 (model 15) andl later have an efficient idle.
-        */
-       if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
-           boot_cpu_data.x86 == 6 &&
-           boot_cpu_data.x86_model >= 15)
-               return 1;
+#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND
+static
 #endif
-       return 0;
-}
-
-static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
-                                  unsigned int event)
-{
-       unsigned int cpu = policy->cpu;
-       struct cpu_dbs_info_s *this_dbs_info;
-       unsigned int j;
-       int rc;
-
-       this_dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
-
-       switch (event) {
-       case CPUFREQ_GOV_START:
-               if ((!cpu_online(cpu)) || (!policy->cur))
-                       return -EINVAL;
-
-               mutex_lock(&dbs_mutex);
-
-               dbs_enable++;
-               for_each_cpu(j, policy->cpus) {
-                       struct cpu_dbs_info_s *j_dbs_info;
-                       j_dbs_info = &per_cpu(od_cpu_dbs_info, j);
-                       j_dbs_info->cur_policy = policy;
-
-                       j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
-                                               &j_dbs_info->prev_cpu_wall);
-                       if (dbs_tuners_ins.ignore_nice)
-                               j_dbs_info->prev_cpu_nice =
-                                               kcpustat_cpu(j).cpustat[CPUTIME_NICE];
-               }
-               this_dbs_info->cpu = cpu;
-               this_dbs_info->rate_mult = 1;
-               ondemand_powersave_bias_init_cpu(cpu);
-               /*
-                * Start the timerschedule work, when this governor
-                * is used for first time
-                */
-               if (dbs_enable == 1) {
-                       unsigned int latency;
-
-                       rc = sysfs_create_group(cpufreq_global_kobject,
-                                               &dbs_attr_group);
-                       if (rc) {
-                               mutex_unlock(&dbs_mutex);
-                               return rc;
-                       }
-
-                       /* policy latency is in nS. Convert it to uS first */
-                       latency = policy->cpuinfo.transition_latency / 1000;
-                       if (latency == 0)
-                               latency = 1;
-                       /* Bring kernel and HW constraints together */
-                       min_sampling_rate = max(min_sampling_rate,
-                                       MIN_LATENCY_MULTIPLIER * latency);
-                       dbs_tuners_ins.sampling_rate =
-                               max(min_sampling_rate,
-                                   latency * LATENCY_MULTIPLIER);
-                       dbs_tuners_ins.io_is_busy = should_io_be_busy();
-               }
-               mutex_unlock(&dbs_mutex);
-
-               mutex_init(&this_dbs_info->timer_mutex);
-               dbs_timer_init(this_dbs_info);
-               break;
-
-       case CPUFREQ_GOV_STOP:
-               dbs_timer_exit(this_dbs_info);
-
-               mutex_lock(&dbs_mutex);
-               mutex_destroy(&this_dbs_info->timer_mutex);
-               dbs_enable--;
-               mutex_unlock(&dbs_mutex);
-               if (!dbs_enable)
-                       sysfs_remove_group(cpufreq_global_kobject,
-                                          &dbs_attr_group);
-
-               break;
-
-       case CPUFREQ_GOV_LIMITS:
-               mutex_lock(&this_dbs_info->timer_mutex);
-               if (policy->max < this_dbs_info->cur_policy->cur)
-                       __cpufreq_driver_target(this_dbs_info->cur_policy,
-                               policy->max, CPUFREQ_RELATION_H);
-               else if (policy->min > this_dbs_info->cur_policy->cur)
-                       __cpufreq_driver_target(this_dbs_info->cur_policy,
-                               policy->min, CPUFREQ_RELATION_L);
-               dbs_check_cpu(this_dbs_info);
-               mutex_unlock(&this_dbs_info->timer_mutex);
-               break;
-       }
-       return 0;
-}
+struct cpufreq_governor cpufreq_gov_ondemand = {
+       .name                   = "ondemand",
+       .governor               = od_cpufreq_governor_dbs,
+       .max_transition_latency = TRANSITION_LATENCY_LIMIT,
+       .owner                  = THIS_MODULE,
+};
 
 static int __init cpufreq_gov_dbs_init(void)
 {
        u64 idle_time;
        int cpu = get_cpu();
 
+       mutex_init(&od_dbs_data.mutex);
        idle_time = get_cpu_idle_time_us(cpu, NULL);
        put_cpu();
        if (idle_time != -1ULL) {
                /* Idle micro accounting is supported. Use finer thresholds */
-               dbs_tuners_ins.up_threshold = MICRO_FREQUENCY_UP_THRESHOLD;
-               dbs_tuners_ins.down_differential =
-                                       MICRO_FREQUENCY_DOWN_DIFFERENTIAL;
+               od_tuners.up_threshold = MICRO_FREQUENCY_UP_THRESHOLD;
+               od_tuners.down_differential = MICRO_FREQUENCY_DOWN_DIFFERENTIAL;
                /*
                 * In nohz/micro accounting case we set the minimum frequency
                 * not depending on HZ, but fixed (very low). The deferred
                 * timer might skip some samples if idle/sleeping as needed.
                */
-               min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE;
+               od_dbs_data.min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE;
        } else {
                /* For correct statistics, we need 10 ticks for each measure */
-               min_sampling_rate =
-                       MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10);
+               od_dbs_data.min_sampling_rate = MIN_SAMPLING_RATE_RATIO *
+                       jiffies_to_usecs(10);
        }
 
        return cpufreq_register_governor(&cpufreq_gov_ondemand);
@@ -800,7 +528,6 @@ static void __exit cpufreq_gov_dbs_exit(void)
        cpufreq_unregister_governor(&cpufreq_gov_ondemand);
 }
 
-
 MODULE_AUTHOR("Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>");
 MODULE_AUTHOR("Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>");
 MODULE_DESCRIPTION("'cpufreq_ondemand' - A dynamic cpufreq governor for "
index f13a8a9..ceee068 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 4c2eb51..2d948a1 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 b40ee14..e40e508 100644 (file)
@@ -37,7 +37,7 @@ struct cpufreq_stats {
        unsigned int max_state;
        unsigned int state_num;
        unsigned int last_index;
-       cputime64_t *time_in_state;
+       u64 *time_in_state;
        unsigned int *freq_table;
 #ifdef CONFIG_CPU_FREQ_STAT_DETAILS
        unsigned int *trans_table;
@@ -223,7 +223,7 @@ static int cpufreq_stats_create_table(struct cpufreq_policy *policy,
                count++;
        }
 
-       alloc_size = count * sizeof(int) + count * sizeof(cputime64_t);
+       alloc_size = count * sizeof(int) + count * sizeof(u64);
 
 #ifdef CONFIG_CPU_FREQ_STAT_DETAILS
        alloc_size += count * count * sizeof(int);
@@ -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 bedac1a..c8c3d29 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 74b830b..4f154bc 100644 (file)
@@ -8,43 +8,17 @@
  * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
  *
  */
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/cpufreq.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
 #include <mach/id.h>
 
-static struct cpufreq_frequency_table freq_table[] = {
-       [0] = {
-               .index = 0,
-               .frequency = 200000,
-       },
-       [1] = {
-               .index = 1,
-               .frequency = 400000,
-       },
-       [2] = {
-               .index = 2,
-               .frequency = 800000,
-       },
-       [3] = {
-               /* Used for MAX_OPP, if available */
-               .index = 3,
-               .frequency = CPUFREQ_TABLE_END,
-       },
-       [4] = {
-               .index = 4,
-               .frequency = CPUFREQ_TABLE_END,
-       },
-};
-
-static enum arm_opp idx2opp[] = {
-       ARM_EXTCLK,
-       ARM_50_OPP,
-       ARM_100_OPP,
-       ARM_MAX_OPP
-};
+static struct cpufreq_frequency_table *freq_table;
+static struct clk *armss_clk;
 
 static struct freq_attr *db8500_cpufreq_attr[] = {
        &cpufreq_freq_attr_scaling_available_freqs,
@@ -85,9 +59,9 @@ static int db8500_cpufreq_target(struct cpufreq_policy *policy,
        for_each_cpu(freqs.cpu, policy->cpus)
                cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
-       /* request the PRCM unit for opp change */
-       if (prcmu_set_arm_opp(idx2opp[idx])) {
-               pr_err("db8500-cpufreq:  Failed to set OPP level\n");
+       /* update armss clk frequency */
+       if (clk_set_rate(armss_clk, freq_table[idx].frequency * 1000)) {
+               pr_err("db8500-cpufreq: Failed to update armss clk\n");
                return -EINVAL;
        }
 
@@ -100,25 +74,36 @@ static int db8500_cpufreq_target(struct cpufreq_policy *policy,
 
 static unsigned int db8500_cpufreq_getspeed(unsigned int cpu)
 {
-       int i;
-       /* request the prcm to get the current ARM opp */
-       for (i = 0; prcmu_get_arm_opp() != idx2opp[i]; i++)
-               ;
-       return freq_table[i].frequency;
+       int i = 0;
+       unsigned long freq = clk_get_rate(armss_clk) / 1000;
+
+       while (freq_table[i].frequency != CPUFREQ_TABLE_END) {
+               if (freq <= freq_table[i].frequency)
+                       return freq_table[i].frequency;
+               i++;
+       }
+
+       /* We could not find a corresponding frequency. */
+       pr_err("db8500-cpufreq: Failed to find cpufreq speed\n");
+       return 0;
 }
 
 static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy)
 {
-       int i, res;
-
-       BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table));
+       int i = 0;
+       int res;
 
-       if (prcmu_has_arm_maxopp())
-               freq_table[3].frequency = 1000000;
+       armss_clk = clk_get(NULL, "armss");
+       if (IS_ERR(armss_clk)) {
+               pr_err("db8500-cpufreq : Failed to get armss clk\n");
+               return PTR_ERR(armss_clk);
+       }
 
        pr_info("db8500-cpufreq : Available frequencies:\n");
-       for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++)
+       while (freq_table[i].frequency != CPUFREQ_TABLE_END) {
                pr_info("  %d Mhz\n", freq_table[i].frequency/1000);
+               i++;
+       }
 
        /* get policy fields based on the table */
        res = cpufreq_frequency_table_cpuinfo(policy, freq_table);
@@ -126,6 +111,7 @@ static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy)
                cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
        else {
                pr_err("db8500-cpufreq : Failed to read policy table\n");
+               clk_put(armss_clk);
                return res;
        }
 
@@ -159,12 +145,35 @@ static struct cpufreq_driver db8500_cpufreq_driver = {
        .attr   = db8500_cpufreq_attr,
 };
 
+static int db8500_cpufreq_probe(struct platform_device *pdev)
+{
+       freq_table = dev_get_platdata(&pdev->dev);
+
+       if (!freq_table) {
+               pr_err("db8500-cpufreq: Failed to fetch cpufreq table\n");
+               return -ENODEV;
+       }
+
+       return cpufreq_register_driver(&db8500_cpufreq_driver);
+}
+
+static struct platform_driver db8500_cpufreq_plat_driver = {
+       .driver = {
+               .name = "cpufreq-u8500",
+               .owner = THIS_MODULE,
+       },
+       .probe = db8500_cpufreq_probe,
+};
+
 static int __init db8500_cpufreq_register(void)
 {
        if (!cpu_is_u8500_family())
                return -ENODEV;
 
        pr_info("cpufreq for DB8500 started\n");
-       return cpufreq_register_driver(&db8500_cpufreq_driver);
+       return platform_driver_register(&db8500_cpufreq_plat_driver);
 }
 device_initcall(db8500_cpufreq_register);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("cpufreq driver for DB8500");
index af2d81e..7012ea8 100644 (file)
@@ -31,13 +31,13 @@ static unsigned int locking_frequency;
 static bool frequency_locked;
 static DEFINE_MUTEX(cpufreq_lock);
 
-int exynos_verify_speed(struct cpufreq_policy *policy)
+static int exynos_verify_speed(struct cpufreq_policy *policy)
 {
        return cpufreq_frequency_table_verify(policy,
                                              exynos_info->freq_table);
 }
 
-unsigned int exynos_getspeed(unsigned int cpu)
+static unsigned int exynos_getspeed(unsigned int cpu)
 {
        return clk_get_rate(exynos_info->cpu_clk) / 1000;
 }
@@ -100,7 +100,8 @@ static int exynos_target(struct cpufreq_policy *policy,
        }
        arm_volt = volt_table[index];
 
-       cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+       for_each_cpu(freqs.cpu, policy->cpus)
+               cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
        /* When the new frequency is higher than current frequency */
        if ((freqs.new > freqs.old) && !safe_arm_volt) {
@@ -115,7 +116,8 @@ static int exynos_target(struct cpufreq_policy *policy,
        if (freqs.new != freqs.old)
                exynos_info->set_freq(old_index, index);
 
-       cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+       for_each_cpu(freqs.cpu, policy->cpus)
+               cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
        /* When the new frequency is lower than current frequency */
        if ((freqs.new < freqs.old) ||
@@ -235,6 +237,7 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
                cpumask_copy(policy->related_cpus, cpu_possible_mask);
                cpumask_copy(policy->cpus, cpu_online_mask);
        } else {
+               policy->shared_type = CPUFREQ_SHARED_TYPE_ANY;
                cpumask_setall(policy->cpus);
        }
 
index 90431cb..49cda25 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 53ddbc7..f1fa500 100644 (file)
@@ -930,7 +930,7 @@ static int __cpuinit longhaul_cpu_init(struct cpufreq_policy *policy)
        return 0;
 }
 
-static int __devexit longhaul_cpu_exit(struct cpufreq_policy *policy)
+static int longhaul_cpu_exit(struct cpufreq_policy *policy)
 {
        cpufreq_frequency_table_put_attr(policy->cpu);
        return 0;
@@ -946,7 +946,7 @@ static struct cpufreq_driver longhaul_driver = {
        .target = longhaul_target,
        .get    = longhaul_get,
        .init   = longhaul_cpu_init,
-       .exit   = __devexit_p(longhaul_cpu_exit),
+       .exit   = longhaul_cpu_exit,
        .name   = "longhaul",
        .owner  = THIS_MODULE,
        .attr   = longhaul_attr,
index 129e80b..056faf6 100644 (file)
@@ -5,7 +5,7 @@
  *  http://www.gnu.org/licenses/gpl.html
  *
  *  Maintainer:
- *  Andreas Herrmann <andreas.herrmann3@amd.com>
+ *  Andreas Herrmann <herrmann.der.user@googlemail.com>
  *
  *  Based on the powernow-k7.c module written by Dave Jones.
  *  (C) 2003 Dave Jones on behalf of SuSE Labs
@@ -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 */
@@ -1193,7 +1186,7 @@ err_out:
        return -ENODEV;
 }
 
-static int __devexit powernowk8_cpu_exit(struct cpufreq_policy *pol)
+static int powernowk8_cpu_exit(struct cpufreq_policy *pol)
 {
        struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
 
@@ -1249,7 +1242,7 @@ static struct cpufreq_driver cpufreq_amd64_driver = {
        .target         = powernowk8_target,
        .bios_limit     = acpi_processor_get_bios_limit,
        .init           = powernowk8_cpu_init,
-       .exit           = __devexit_p(powernowk8_cpu_exit),
+       .exit           = powernowk8_cpu_exit,
        .get            = powernowk8_get,
        .name           = "powernow-k8",
        .owner          = THIS_MODULE,
diff --git a/drivers/cpufreq/spear-cpufreq.c b/drivers/cpufreq/spear-cpufreq.c
new file mode 100644 (file)
index 0000000..4575cfe
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * drivers/cpufreq/spear-cpufreq.c
+ *
+ * CPU Frequency Scaling for SPEAr platform
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Deepak Sikri <deepak.sikri@st.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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/clk.h>
+#include <linux/cpufreq.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+/* SPEAr CPUFreq driver data structure */
+static struct {
+       struct clk *clk;
+       unsigned int transition_latency;
+       struct cpufreq_frequency_table *freq_tbl;
+       u32 cnt;
+} spear_cpufreq;
+
+int spear_cpufreq_verify(struct cpufreq_policy *policy)
+{
+       return cpufreq_frequency_table_verify(policy, spear_cpufreq.freq_tbl);
+}
+
+static unsigned int spear_cpufreq_get(unsigned int cpu)
+{
+       return clk_get_rate(spear_cpufreq.clk) / 1000;
+}
+
+static struct clk *spear1340_cpu_get_possible_parent(unsigned long newfreq)
+{
+       struct clk *sys_pclk;
+       int pclk;
+       /*
+        * In SPEAr1340, cpu clk's parent sys clk can take input from
+        * following sources
+        */
+       const char *sys_clk_src[] = {
+               "sys_syn_clk",
+               "pll1_clk",
+               "pll2_clk",
+               "pll3_clk",
+       };
+
+       /*
+        * As sys clk can have multiple source with their own range
+        * limitation so we choose possible sources accordingly
+        */
+       if (newfreq <= 300000000)
+               pclk = 0; /* src is sys_syn_clk */
+       else if (newfreq > 300000000 && newfreq <= 500000000)
+               pclk = 3; /* src is pll3_clk */
+       else if (newfreq == 600000000)
+               pclk = 1; /* src is pll1_clk */
+       else
+               return ERR_PTR(-EINVAL);
+
+       /* Get parent to sys clock */
+       sys_pclk = clk_get(NULL, sys_clk_src[pclk]);
+       if (IS_ERR(sys_pclk))
+               pr_err("Failed to get %s clock\n", sys_clk_src[pclk]);
+
+       return sys_pclk;
+}
+
+/*
+ * In SPEAr1340, we cannot use newfreq directly because we need to actually
+ * access a source clock (clk) which might not be ancestor of cpu at present.
+ * Hence in SPEAr1340 we would operate on source clock directly before switching
+ * cpu clock to it.
+ */
+static int spear1340_set_cpu_rate(struct clk *sys_pclk, unsigned long newfreq)
+{
+       struct clk *sys_clk;
+       int ret = 0;
+
+       sys_clk = clk_get_parent(spear_cpufreq.clk);
+       if (IS_ERR(sys_clk)) {
+               pr_err("failed to get cpu's parent (sys) clock\n");
+               return PTR_ERR(sys_clk);
+       }
+
+       /* Set the rate of the source clock before changing the parent */
+       ret = clk_set_rate(sys_pclk, newfreq);
+       if (ret) {
+               pr_err("Failed to set sys clk rate to %lu\n", newfreq);
+               return ret;
+       }
+
+       ret = clk_set_parent(sys_clk, sys_pclk);
+       if (ret) {
+               pr_err("Failed to set sys clk parent\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int spear_cpufreq_target(struct cpufreq_policy *policy,
+               unsigned int target_freq, unsigned int relation)
+{
+       struct cpufreq_freqs freqs;
+       unsigned long newfreq;
+       struct clk *srcclk;
+       int index, ret, mult = 1;
+
+       if (cpufreq_frequency_table_target(policy, spear_cpufreq.freq_tbl,
+                               target_freq, relation, &index))
+               return -EINVAL;
+
+       freqs.cpu = policy->cpu;
+       freqs.old = spear_cpufreq_get(0);
+
+       newfreq = spear_cpufreq.freq_tbl[index].frequency * 1000;
+       if (of_machine_is_compatible("st,spear1340")) {
+               /*
+                * SPEAr1340 is special in the sense that due to the possibility
+                * of multiple clock sources for cpu clk's parent we can have
+                * different clock source for different frequency of cpu clk.
+                * Hence we need to choose one from amongst these possible clock
+                * sources.
+                */
+               srcclk = spear1340_cpu_get_possible_parent(newfreq);
+               if (IS_ERR(srcclk)) {
+                       pr_err("Failed to get src clk\n");
+                       return PTR_ERR(srcclk);
+               }
+
+               /* SPEAr1340: src clk is always 2 * intended cpu clk */
+               mult = 2;
+       } else {
+               /*
+                * src clock to be altered is ancestor of cpu clock. Hence we
+                * can directly work on cpu clk
+                */
+               srcclk = spear_cpufreq.clk;
+       }
+
+       newfreq = clk_round_rate(srcclk, newfreq * mult);
+       if (newfreq < 0) {
+               pr_err("clk_round_rate failed for cpu src clock\n");
+               return newfreq;
+       }
+
+       freqs.new = newfreq / 1000;
+       freqs.new /= mult;
+       cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+       if (mult == 2)
+               ret = spear1340_set_cpu_rate(srcclk, newfreq);
+       else
+               ret = clk_set_rate(spear_cpufreq.clk, newfreq);
+
+       /* Get current rate after clk_set_rate, in case of failure */
+       if (ret) {
+               pr_err("CPU Freq: cpu clk_set_rate failed: %d\n", ret);
+               freqs.new = clk_get_rate(spear_cpufreq.clk) / 1000;
+       }
+
+       cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+       return ret;
+}
+
+static int spear_cpufreq_init(struct cpufreq_policy *policy)
+{
+       int ret;
+
+       ret = cpufreq_frequency_table_cpuinfo(policy, spear_cpufreq.freq_tbl);
+       if (ret) {
+               pr_err("cpufreq_frequency_table_cpuinfo() failed");
+               return ret;
+       }
+
+       cpufreq_frequency_table_get_attr(spear_cpufreq.freq_tbl, policy->cpu);
+       policy->cpuinfo.transition_latency = spear_cpufreq.transition_latency;
+       policy->cur = spear_cpufreq_get(0);
+
+       cpumask_copy(policy->cpus, topology_core_cpumask(policy->cpu));
+       cpumask_copy(policy->related_cpus, policy->cpus);
+
+       return 0;
+}
+
+static int spear_cpufreq_exit(struct cpufreq_policy *policy)
+{
+       cpufreq_frequency_table_put_attr(policy->cpu);
+       return 0;
+}
+
+static struct freq_attr *spear_cpufreq_attr[] = {
+        &cpufreq_freq_attr_scaling_available_freqs,
+        NULL,
+};
+
+static struct cpufreq_driver spear_cpufreq_driver = {
+       .name           = "cpufreq-spear",
+       .flags          = CPUFREQ_STICKY,
+       .verify         = spear_cpufreq_verify,
+       .target         = spear_cpufreq_target,
+       .get            = spear_cpufreq_get,
+       .init           = spear_cpufreq_init,
+       .exit           = spear_cpufreq_exit,
+       .attr           = spear_cpufreq_attr,
+};
+
+static int spear_cpufreq_driver_init(void)
+{
+       struct device_node *np;
+       const struct property *prop;
+       struct cpufreq_frequency_table *freq_tbl;
+       const __be32 *val;
+       int cnt, i, ret;
+
+       np = of_find_node_by_path("/cpus/cpu@0");
+       if (!np) {
+               pr_err("No cpu node found");
+               return -ENODEV;
+       }
+
+       if (of_property_read_u32(np, "clock-latency",
+                               &spear_cpufreq.transition_latency))
+               spear_cpufreq.transition_latency = CPUFREQ_ETERNAL;
+
+       prop = of_find_property(np, "cpufreq_tbl", NULL);
+       if (!prop || !prop->value) {
+               pr_err("Invalid cpufreq_tbl");
+               ret = -ENODEV;
+               goto out_put_node;
+       }
+
+       cnt = prop->length / sizeof(u32);
+       val = prop->value;
+
+       freq_tbl = kmalloc(sizeof(*freq_tbl) * (cnt + 1), GFP_KERNEL);
+       if (!freq_tbl) {
+               ret = -ENOMEM;
+               goto out_put_node;
+       }
+
+       for (i = 0; i < cnt; i++) {
+               freq_tbl[i].index = i;
+               freq_tbl[i].frequency = be32_to_cpup(val++);
+       }
+
+       freq_tbl[i].index = i;
+       freq_tbl[i].frequency = CPUFREQ_TABLE_END;
+
+       spear_cpufreq.freq_tbl = freq_tbl;
+
+       of_node_put(np);
+
+       spear_cpufreq.clk = clk_get(NULL, "cpu_clk");
+       if (IS_ERR(spear_cpufreq.clk)) {
+               pr_err("Unable to get CPU clock\n");
+               ret = PTR_ERR(spear_cpufreq.clk);
+               goto out_put_mem;
+       }
+
+       ret = cpufreq_register_driver(&spear_cpufreq_driver);
+       if (!ret)
+               return 0;
+
+       pr_err("failed register driver: %d\n", ret);
+       clk_put(spear_cpufreq.clk);
+
+out_put_mem:
+       kfree(freq_tbl);
+       return ret;
+
+out_put_node:
+       of_node_put(np);
+       return ret;
+}
+late_initcall(spear_cpufreq_driver_init);
+
+MODULE_AUTHOR("Deepak Sikri <deepak.sikri@st.com>");
+MODULE_DESCRIPTION("SPEAr CPUFreq driver");
+MODULE_LICENSE("GPL");
index a76b689..234ae65 100644 (file)
@@ -9,6 +9,15 @@ config CPU_IDLE
 
          If you're using an ACPI-enabled platform, you should say Y here.
 
+config CPU_IDLE_MULTIPLE_DRIVERS
+        bool "Support multiple cpuidle drivers"
+        depends on CPU_IDLE
+        default n
+        help
+         Allows the cpuidle framework to use different drivers for each CPU.
+         This is useful if you have a system with different CPU latencies and
+         states. If unsure say N.
+
 config CPU_IDLE_GOV_LADDER
        bool
        depends on CPU_IDLE
index 7f15b85..8df53dd 100644 (file)
@@ -68,7 +68,7 @@ static cpuidle_enter_t cpuidle_enter_ops;
 int cpuidle_play_dead(void)
 {
        struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
-       struct cpuidle_driver *drv = cpuidle_get_driver();
+       struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
        int i, dead_state = -1;
        int power_usage = -1;
 
@@ -109,8 +109,7 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv,
                /* This can be moved to within driver enter routine
                 * but that results in multiple copies of same code.
                 */
-               dev->states_usage[entered_state].time +=
-                               (unsigned long long)dev->last_residency;
+               dev->states_usage[entered_state].time += dev->last_residency;
                dev->states_usage[entered_state].usage++;
        } else {
                dev->last_residency = 0;
@@ -128,7 +127,7 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv,
 int cpuidle_idle_call(void)
 {
        struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
-       struct cpuidle_driver *drv = cpuidle_get_driver();
+       struct cpuidle_driver *drv;
        int next_state, entered_state;
 
        if (off)
@@ -141,9 +140,15 @@ int cpuidle_idle_call(void)
        if (!dev || !dev->enabled)
                return -EBUSY;
 
+       drv = cpuidle_get_cpu_driver(dev);
+
        /* 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;
        }
@@ -308,15 +313,19 @@ static void poll_idle_init(struct cpuidle_driver *drv) {}
 int cpuidle_enable_device(struct cpuidle_device *dev)
 {
        int ret, i;
-       struct cpuidle_driver *drv = cpuidle_get_driver();
+       struct cpuidle_driver *drv;
 
        if (!dev)
                return -EINVAL;
 
        if (dev->enabled)
                return 0;
+
+       drv = cpuidle_get_cpu_driver(dev);
+
        if (!drv || !cpuidle_curr_governor)
                return -EIO;
+
        if (!dev->state_count)
                dev->state_count = drv->state_count;
 
@@ -331,7 +340,8 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
 
        poll_idle_init(drv);
 
-       if ((ret = cpuidle_add_state_sysfs(dev)))
+       ret = cpuidle_add_device_sysfs(dev);
+       if (ret)
                return ret;
 
        if (cpuidle_curr_governor->enable &&
@@ -352,7 +362,7 @@ int cpuidle_enable_device(struct cpuidle_device *dev)
        return 0;
 
 fail_sysfs:
-       cpuidle_remove_state_sysfs(dev);
+       cpuidle_remove_device_sysfs(dev);
 
        return ret;
 }
@@ -368,17 +378,20 @@ EXPORT_SYMBOL_GPL(cpuidle_enable_device);
  */
 void cpuidle_disable_device(struct cpuidle_device *dev)
 {
+       struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
+
        if (!dev || !dev->enabled)
                return;
-       if (!cpuidle_get_driver() || !cpuidle_curr_governor)
+
+       if (!drv || !cpuidle_curr_governor)
                return;
 
        dev->enabled = 0;
 
        if (cpuidle_curr_governor->disable)
-               cpuidle_curr_governor->disable(cpuidle_get_driver(), dev);
+               cpuidle_curr_governor->disable(drv, dev);
 
-       cpuidle_remove_state_sysfs(dev);
+       cpuidle_remove_device_sysfs(dev);
        enabled_devices--;
 }
 
@@ -394,17 +407,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();
+       struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
 
-       if (!try_module_get(cpuidle_driver->owner))
+       if (!try_module_get(drv->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,12 +426,11 @@ 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;
-       module_put(cpuidle_driver->owner);
+       module_put(drv->owner);
        return ret;
 }
 
@@ -460,8 +469,7 @@ 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();
+       struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
 
        if (dev->registered == 0)
                return;
@@ -470,16 +478,15 @@ 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);
 
        cpuidle_resume_and_unlock();
 
-       module_put(cpuidle_driver->owner);
+       module_put(drv->owner);
 }
 
 EXPORT_SYMBOL_GPL(cpuidle_unregister_device);
index 76e7f69..ee97e96 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;
@@ -25,12 +23,15 @@ extern void cpuidle_uninstall_idle_handler(void);
 extern int cpuidle_switch_governor(struct cpuidle_governor *gov);
 
 /* sysfs */
+
+struct device;
+
 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_device_sysfs(struct cpuidle_device *device);
+extern void cpuidle_remove_device_sysfs(struct cpuidle_device *device);
+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 87db387..3af841f 100644 (file)
 
 #include "cpuidle.h"
 
-static struct cpuidle_driver *cpuidle_curr_driver;
 DEFINE_SPINLOCK(cpuidle_driver_lock);
-int cpuidle_driver_refcount;
+
+static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu);
+static struct cpuidle_driver * __cpuidle_get_cpu_driver(int cpu);
 
 static void set_power_states(struct cpuidle_driver *drv)
 {
@@ -40,11 +41,15 @@ static void set_power_states(struct cpuidle_driver *drv)
                drv->states[i].power_usage = -1 - i;
 }
 
-/**
- * cpuidle_register_driver - registers a driver
- * @drv: the driver
- */
-int cpuidle_register_driver(struct cpuidle_driver *drv)
+static void __cpuidle_driver_init(struct cpuidle_driver *drv)
+{
+       drv->refcnt = 0;
+
+       if (!drv->power_specified)
+               set_power_states(drv);
+}
+
+static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu)
 {
        if (!drv || !drv->state_count)
                return -EINVAL;
@@ -52,31 +57,145 @@ int cpuidle_register_driver(struct cpuidle_driver *drv)
        if (cpuidle_disabled())
                return -ENODEV;
 
-       spin_lock(&cpuidle_driver_lock);
-       if (cpuidle_curr_driver) {
-               spin_unlock(&cpuidle_driver_lock);
+       if (__cpuidle_get_cpu_driver(cpu))
                return -EBUSY;
+
+       __cpuidle_driver_init(drv);
+
+       __cpuidle_set_cpu_driver(drv, cpu);
+
+       return 0;
+}
+
+static void __cpuidle_unregister_driver(struct cpuidle_driver *drv, int cpu)
+{
+       if (drv != __cpuidle_get_cpu_driver(cpu))
+               return;
+
+       if (!WARN_ON(drv->refcnt > 0))
+               __cpuidle_set_cpu_driver(NULL, cpu);
+}
+
+#ifdef CONFIG_CPU_IDLE_MULTIPLE_DRIVERS
+
+static DEFINE_PER_CPU(struct cpuidle_driver *, cpuidle_drivers);
+
+static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu)
+{
+       per_cpu(cpuidle_drivers, cpu) = drv;
+}
+
+static struct cpuidle_driver *__cpuidle_get_cpu_driver(int cpu)
+{
+       return per_cpu(cpuidle_drivers, cpu);
+}
+
+static void __cpuidle_unregister_all_cpu_driver(struct cpuidle_driver *drv)
+{
+       int cpu;
+       for_each_present_cpu(cpu)
+               __cpuidle_unregister_driver(drv, cpu);
+}
+
+static int __cpuidle_register_all_cpu_driver(struct cpuidle_driver *drv)
+{
+       int ret = 0;
+       int i, cpu;
+
+       for_each_present_cpu(cpu) {
+               ret = __cpuidle_register_driver(drv, cpu);
+               if (ret)
+                       break;
        }
 
-       if (!drv->power_specified)
-               set_power_states(drv);
+       if (ret)
+               for_each_present_cpu(i) {
+                       if (i == cpu)
+                               break;
+                       __cpuidle_unregister_driver(drv, i);
+               }
 
-       cpuidle_curr_driver = drv;
 
+       return ret;
+}
+
+int cpuidle_register_cpu_driver(struct cpuidle_driver *drv, int cpu)
+{
+       int ret;
+
+       spin_lock(&cpuidle_driver_lock);
+       ret = __cpuidle_register_driver(drv, cpu);
        spin_unlock(&cpuidle_driver_lock);
 
-       return 0;
+       return ret;
+}
+
+void cpuidle_unregister_cpu_driver(struct cpuidle_driver *drv, int cpu)
+{
+       spin_lock(&cpuidle_driver_lock);
+       __cpuidle_unregister_driver(drv, cpu);
+       spin_unlock(&cpuidle_driver_lock);
+}
+
+/**
+ * cpuidle_register_driver - registers a driver
+ * @drv: the driver
+ */
+int cpuidle_register_driver(struct cpuidle_driver *drv)
+{
+       int ret;
+
+       spin_lock(&cpuidle_driver_lock);
+       ret = __cpuidle_register_all_cpu_driver(drv);
+       spin_unlock(&cpuidle_driver_lock);
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(cpuidle_register_driver);
 
 /**
- * cpuidle_get_driver - return the current driver
+ * cpuidle_unregister_driver - unregisters a driver
+ * @drv: the driver
  */
-struct cpuidle_driver *cpuidle_get_driver(void)
+void cpuidle_unregister_driver(struct cpuidle_driver *drv)
+{
+       spin_lock(&cpuidle_driver_lock);
+       __cpuidle_unregister_all_cpu_driver(drv);
+       spin_unlock(&cpuidle_driver_lock);
+}
+EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
+
+#else
+
+static struct cpuidle_driver *cpuidle_curr_driver;
+
+static inline void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu)
+{
+       cpuidle_curr_driver = drv;
+}
+
+static inline struct cpuidle_driver *__cpuidle_get_cpu_driver(int cpu)
 {
        return cpuidle_curr_driver;
 }
-EXPORT_SYMBOL_GPL(cpuidle_get_driver);
+
+/**
+ * cpuidle_register_driver - registers a driver
+ * @drv: the driver
+ */
+int cpuidle_register_driver(struct cpuidle_driver *drv)
+{
+       int ret, cpu;
+
+       cpu = get_cpu();
+       spin_lock(&cpuidle_driver_lock);
+       ret = __cpuidle_register_driver(drv, cpu);
+       spin_unlock(&cpuidle_driver_lock);
+       put_cpu();
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(cpuidle_register_driver);
 
 /**
  * cpuidle_unregister_driver - unregisters a driver
@@ -84,20 +203,50 @@ EXPORT_SYMBOL_GPL(cpuidle_get_driver);
  */
 void cpuidle_unregister_driver(struct cpuidle_driver *drv)
 {
-       if (drv != cpuidle_curr_driver) {
-               WARN(1, "invalid cpuidle_unregister_driver(%s)\n",
-                       drv->name);
-               return;
-       }
+       int cpu;
 
+       cpu = get_cpu();
        spin_lock(&cpuidle_driver_lock);
+       __cpuidle_unregister_driver(drv, cpu);
+       spin_unlock(&cpuidle_driver_lock);
+       put_cpu();
+}
+EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
+#endif
+
+/**
+ * cpuidle_get_driver - return the current driver
+ */
+struct cpuidle_driver *cpuidle_get_driver(void)
+{
+       struct cpuidle_driver *drv;
+       int cpu;
 
-       if (!WARN_ON(cpuidle_driver_refcount > 0))
-               cpuidle_curr_driver = NULL;
+       cpu = get_cpu();
+       drv = __cpuidle_get_cpu_driver(cpu);
+       put_cpu();
 
+       return drv;
+}
+EXPORT_SYMBOL_GPL(cpuidle_get_driver);
+
+/**
+ * cpuidle_get_cpu_driver - return the driver tied with a cpu
+ */
+struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev)
+{
+       struct cpuidle_driver *drv;
+
+       if (!dev)
+               return NULL;
+
+       spin_lock(&cpuidle_driver_lock);
+       drv = __cpuidle_get_cpu_driver(dev->cpu);
        spin_unlock(&cpuidle_driver_lock);
+
+       return drv;
 }
-EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
+EXPORT_SYMBOL_GPL(cpuidle_get_cpu_driver);
 
 struct cpuidle_driver *cpuidle_driver_ref(void)
 {
@@ -105,8 +254,8 @@ struct cpuidle_driver *cpuidle_driver_ref(void)
 
        spin_lock(&cpuidle_driver_lock);
 
-       drv = cpuidle_curr_driver;
-       cpuidle_driver_refcount++;
+       drv = cpuidle_get_driver();
+       drv->refcnt++;
 
        spin_unlock(&cpuidle_driver_lock);
        return drv;
@@ -114,10 +263,12 @@ struct cpuidle_driver *cpuidle_driver_ref(void)
 
 void cpuidle_driver_unref(void)
 {
+       struct cpuidle_driver *drv = cpuidle_get_driver();
+
        spin_lock(&cpuidle_driver_lock);
 
-       if (!WARN_ON(cpuidle_driver_refcount <= 0))
-               cpuidle_driver_refcount--;
+       if (drv && !WARN_ON(drv->refcnt <= 0))
+               drv->refcnt--;
 
        spin_unlock(&cpuidle_driver_lock);
 }
index 5b1f2c3..bd40b94 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,44 @@ 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)) {
+                       RCU_NONIDLE(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.
+                        */
+                       RCU_NONIDLE(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 +518,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 5f809e3..3409429 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <linux/cpu.h>
 #include <linux/capability.h>
+#include <linux/device.h>
 
 #include "cpuidle.h"
 
@@ -297,6 +298,13 @@ static struct attribute *cpuidle_state_default_attrs[] = {
        NULL
 };
 
+struct cpuidle_state_kobj {
+       struct cpuidle_state *state;
+       struct cpuidle_state_usage *state_usage;
+       struct completion kobj_unregister;
+       struct kobject kobj;
+};
+
 #define kobj_to_state_obj(k) container_of(k, struct cpuidle_state_kobj, kobj)
 #define kobj_to_state(k) (kobj_to_state_obj(k)->state)
 #define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage)
@@ -356,17 +364,17 @@ static inline void cpuidle_free_state_kobj(struct cpuidle_device *device, int i)
 }
 
 /**
- * cpuidle_add_driver_sysfs - adds driver-specific sysfs attributes
+ * cpuidle_add_state_sysfs - adds cpuidle states sysfs attributes
  * @device: the target device
  */
-int cpuidle_add_state_sysfs(struct cpuidle_device *device)
+static int cpuidle_add_state_sysfs(struct cpuidle_device *device)
 {
        int i, ret = -ENOMEM;
        struct cpuidle_state_kobj *kobj;
-       struct cpuidle_driver *drv = cpuidle_get_driver();
+       struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device);
 
        /* state statistics */
-       for (i = 0; i < device->state_count; i++) {
+       for (i = 0; i < drv->state_count; i++) {
                kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL);
                if (!kobj)
                        goto error_state;
@@ -374,8 +382,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;
@@ -393,10 +401,10 @@ error_state:
 }
 
 /**
- * cpuidle_remove_driver_sysfs - removes driver-specific sysfs attributes
+ * cpuidle_remove_driver_sysfs - removes the cpuidle states sysfs attributes
  * @device: the target device
  */
-void cpuidle_remove_state_sysfs(struct cpuidle_device *device)
+static void cpuidle_remove_state_sysfs(struct cpuidle_device *device)
 {
        int i;
 
@@ -404,17 +412,179 @@ void cpuidle_remove_state_sysfs(struct cpuidle_device *device)
                cpuidle_free_state_kobj(device, i);
 }
 
+#ifdef CONFIG_CPU_IDLE_MULTIPLE_DRIVERS
+#define kobj_to_driver_kobj(k) container_of(k, struct cpuidle_driver_kobj, kobj)
+#define attr_to_driver_attr(a) container_of(a, struct cpuidle_driver_attr, attr)
+
+#define define_one_driver_ro(_name, show)                       \
+       static struct cpuidle_driver_attr attr_driver_##_name = \
+               __ATTR(_name, 0644, show, NULL)
+
+struct cpuidle_driver_kobj {
+       struct cpuidle_driver *drv;
+       struct completion kobj_unregister;
+       struct kobject kobj;
+};
+
+struct cpuidle_driver_attr {
+       struct attribute attr;
+       ssize_t (*show)(struct cpuidle_driver *, char *);
+       ssize_t (*store)(struct cpuidle_driver *, const char *, size_t);
+};
+
+static ssize_t show_driver_name(struct cpuidle_driver *drv, char *buf)
+{
+       ssize_t ret;
+
+       spin_lock(&cpuidle_driver_lock);
+       ret = sprintf(buf, "%s\n", drv ? drv->name : "none");
+       spin_unlock(&cpuidle_driver_lock);
+
+       return ret;
+}
+
+static void cpuidle_driver_sysfs_release(struct kobject *kobj)
+{
+       struct cpuidle_driver_kobj *driver_kobj = kobj_to_driver_kobj(kobj);
+       complete(&driver_kobj->kobj_unregister);
+}
+
+static ssize_t cpuidle_driver_show(struct kobject *kobj, struct attribute * attr,
+                                  char * buf)
+{
+       int ret = -EIO;
+       struct cpuidle_driver_kobj *driver_kobj = kobj_to_driver_kobj(kobj);
+       struct cpuidle_driver_attr *dattr = attr_to_driver_attr(attr);
+
+       if (dattr->show)
+               ret = dattr->show(driver_kobj->drv, buf);
+
+       return ret;
+}
+
+static ssize_t cpuidle_driver_store(struct kobject *kobj, struct attribute *attr,
+                                   const char *buf, size_t size)
+{
+       int ret = -EIO;
+       struct cpuidle_driver_kobj *driver_kobj = kobj_to_driver_kobj(kobj);
+       struct cpuidle_driver_attr *dattr = attr_to_driver_attr(attr);
+
+       if (dattr->store)
+               ret = dattr->store(driver_kobj->drv, buf, size);
+
+       return ret;
+}
+
+define_one_driver_ro(name, show_driver_name);
+
+static const struct sysfs_ops cpuidle_driver_sysfs_ops = {
+       .show = cpuidle_driver_show,
+       .store = cpuidle_driver_store,
+};
+
+static struct attribute *cpuidle_driver_default_attrs[] = {
+       &attr_driver_name.attr,
+       NULL
+};
+
+static struct kobj_type ktype_driver_cpuidle = {
+       .sysfs_ops = &cpuidle_driver_sysfs_ops,
+       .default_attrs = cpuidle_driver_default_attrs,
+       .release = cpuidle_driver_sysfs_release,
+};
+
+/**
+ * cpuidle_add_driver_sysfs - adds the driver name sysfs attribute
+ * @device: the target device
+ */
+static int cpuidle_add_driver_sysfs(struct cpuidle_device *dev)
+{
+       struct cpuidle_driver_kobj *kdrv;
+       struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
+       int ret;
+
+       kdrv = kzalloc(sizeof(*kdrv), GFP_KERNEL);
+       if (!kdrv)
+               return -ENOMEM;
+
+       kdrv->drv = drv;
+       init_completion(&kdrv->kobj_unregister);
+
+       ret = kobject_init_and_add(&kdrv->kobj, &ktype_driver_cpuidle,
+                                  &dev->kobj, "driver");
+       if (ret) {
+               kfree(kdrv);
+               return ret;
+       }
+
+       kobject_uevent(&kdrv->kobj, KOBJ_ADD);
+       dev->kobj_driver = kdrv;
+
+       return ret;
+}
+
+/**
+ * cpuidle_remove_driver_sysfs - removes the driver name sysfs attribute
+ * @device: the target device
+ */
+static void cpuidle_remove_driver_sysfs(struct cpuidle_device *dev)
+{
+       struct cpuidle_driver_kobj *kdrv = dev->kobj_driver;
+       kobject_put(&kdrv->kobj);
+       wait_for_completion(&kdrv->kobj_unregister);
+       kfree(kdrv);
+}
+#else
+static inline int cpuidle_add_driver_sysfs(struct cpuidle_device *dev)
+{
+       return 0;
+}
+
+static inline void cpuidle_remove_driver_sysfs(struct cpuidle_device *dev)
+{
+       ;
+}
+#endif
+
+/**
+ * cpuidle_add_device_sysfs - adds device specific sysfs attributes
+ * @device: the target device
+ */
+int cpuidle_add_device_sysfs(struct cpuidle_device *device)
+{
+       int ret;
+
+       ret = cpuidle_add_state_sysfs(device);
+       if (ret)
+               return ret;
+
+       ret = cpuidle_add_driver_sysfs(device);
+       if (ret)
+               cpuidle_remove_state_sysfs(device);
+       return ret;
+}
+
+/**
+ * cpuidle_remove_device_sysfs : removes device specific sysfs attributes
+ * @device : the target device
+ */
+void cpuidle_remove_device_sysfs(struct cpuidle_device *device)
+{
+       cpuidle_remove_driver_sysfs(device);
+       cpuidle_remove_state_sysfs(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 +596,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 308c7fb..f6644f5 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 8f3f74c..21180d6 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 f6b0a6e..0f079be 100644 (file)
@@ -30,7 +30,7 @@ if PM_DEVFREQ
 comment "DEVFREQ Governors"
 
 config DEVFREQ_GOV_SIMPLE_ONDEMAND
-       bool "Simple Ondemand"
+       tristate "Simple Ondemand"
        help
          Chooses frequency based on the recent load on the device. Works
          similar as ONDEMAND governor of CPUFREQ does. A device with
@@ -39,7 +39,7 @@ config DEVFREQ_GOV_SIMPLE_ONDEMAND
          values to the governor with data field at devfreq_add_device().
 
 config DEVFREQ_GOV_PERFORMANCE
-       bool "Performance"
+       tristate "Performance"
        help
          Sets the frequency at the maximum available frequency.
          This governor always returns UINT_MAX as frequency so that
@@ -47,7 +47,7 @@ config DEVFREQ_GOV_PERFORMANCE
          at any time.
 
 config DEVFREQ_GOV_POWERSAVE
-       bool "Powersave"
+       tristate "Powersave"
        help
          Sets the frequency at the minimum available frequency.
          This governor always returns 0 as frequency so that
@@ -55,7 +55,7 @@ config DEVFREQ_GOV_POWERSAVE
          at any time.
 
 config DEVFREQ_GOV_USERSPACE
-       bool "Userspace"
+       tristate "Userspace"
        help
          Sets the frequency at the user specified one.
          This governor returns the user configured frequency if there
index b146d76..53766f3 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 governors */
+static LIST_HEAD(devfreq_governor_list);
 /* The list of all device-devfreq */
 static LIST_HEAD(devfreq_list);
 static DEFINE_MUTEX(devfreq_list_lock);
@@ -73,6 +69,79 @@ static struct devfreq *find_device_devfreq(struct device *dev)
 }
 
 /**
+ * devfreq_get_freq_level() - Lookup freq_table for the frequency
+ * @devfreq:   the devfreq instance
+ * @freq:      the target frequency
+ */
+static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq)
+{
+       int lev;
+
+       for (lev = 0; lev < devfreq->profile->max_state; lev++)
+               if (freq == devfreq->profile->freq_table[lev])
+                       return lev;
+
+       return -EINVAL;
+}
+
+/**
+ * devfreq_update_status() - Update statistics of devfreq behavior
+ * @devfreq:   the devfreq instance
+ * @freq:      the update target frequency
+ */
+static int devfreq_update_status(struct devfreq *devfreq, unsigned long freq)
+{
+       int lev, prev_lev;
+       unsigned long cur_time;
+
+       lev = devfreq_get_freq_level(devfreq, freq);
+       if (lev < 0)
+               return lev;
+
+       cur_time = jiffies;
+       devfreq->time_in_state[lev] +=
+                        cur_time - devfreq->last_stat_updated;
+       if (freq != devfreq->previous_freq) {
+               prev_lev = devfreq_get_freq_level(devfreq,
+                                               devfreq->previous_freq);
+               devfreq->trans_table[(prev_lev *
+                               devfreq->profile->max_state) + lev]++;
+               devfreq->total_trans++;
+       }
+       devfreq->last_stat_updated = cur_time;
+
+       return 0;
+}
+
+/**
+ * find_devfreq_governor() - find devfreq governor from name
+ * @name:      name of the governor
+ *
+ * Search the list of devfreq governors and return the matched
+ * governor's pointer. devfreq_list_lock should be held by the caller.
+ */
+static struct devfreq_governor *find_devfreq_governor(const char *name)
+{
+       struct devfreq_governor *tmp_governor;
+
+       if (unlikely(IS_ERR_OR_NULL(name))) {
+               pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
+               return ERR_PTR(-EINVAL);
+       }
+       WARN(!mutex_is_locked(&devfreq_list_lock),
+            "devfreq_list_lock must be locked.");
+
+       list_for_each_entry(tmp_governor, &devfreq_governor_list, node) {
+               if (!strncmp(tmp_governor->name, name, DEVFREQ_NAME_LEN))
+                       return tmp_governor;
+       }
+
+       return ERR_PTR(-ENODEV);
+}
+
+/* Load monitoring helper functions for governors use */
+
+/**
  * update_devfreq() - Reevaluate the device and configure frequency.
  * @devfreq:   the devfreq instance.
  *
@@ -90,6 +159,9 @@ int update_devfreq(struct devfreq *devfreq)
                return -EINVAL;
        }
 
+       if (!devfreq->governor)
+               return -EINVAL;
+
        /* Reevaluate the proper frequency */
        err = devfreq->governor->get_target_freq(devfreq, &freq);
        if (err)
@@ -116,16 +188,173 @@ int update_devfreq(struct devfreq *devfreq)
        if (err)
                return err;
 
+       if (devfreq->profile->freq_table)
+               if (devfreq_update_status(devfreq, freq))
+                       dev_err(&devfreq->dev,
+                               "Couldn't update frequency transition information.\n");
+
        devfreq->previous_freq = freq;
        return err;
 }
+EXPORT_SYMBOL(update_devfreq);
+
+/**
+ * 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));
+}
+EXPORT_SYMBOL(devfreq_monitor_start);
+
+/**
+ * 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);
+}
+EXPORT_SYMBOL(devfreq_monitor_stop);
+
+/**
+ * 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);
+}
+EXPORT_SYMBOL(devfreq_monitor_suspend);
+
+/**
+ * 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);
+}
+EXPORT_SYMBOL(devfreq_monitor_resume);
+
+/**
+ * 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);
+}
+EXPORT_SYMBOL(devfreq_interval_update);
 
 /**
  * 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 +372,34 @@ 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 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;
+       if (devfreq->governor)
+               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,163 +414,39 @@ 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;
-       }
 }
 
 /**
  * devfreq_add_device() - Add devfreq feature to the device
  * @dev:       the device to add devfreq feature.
  * @profile:   device-specific profile to run devfreq.
- * @governor the policy to choose frequency.
+ * @governor_name:     name of the policy to choose frequency.
  * @data:      private data for the governor. The devfreq framework does not
  *             touch this value.
  */
 struct devfreq *devfreq_add_device(struct device *dev,
                                   struct devfreq_dev_profile *profile,
-                                  const struct devfreq_governor *governor,
+                                  const char *governor_name,
                                   void *data)
 {
        struct devfreq *devfreq;
+       struct devfreq_governor *governor;
        int err = 0;
 
-       if (!dev || !profile || !governor) {
+       if (!dev || !profile || !governor_name) {
                dev_err(dev, "%s: Invalid parameters.\n", __func__);
                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);
@@ -383,92 +463,316 @@ struct devfreq *devfreq_add_device(struct device *dev,
        devfreq->dev.class = devfreq_class;
        devfreq->dev.release = devfreq_dev_release;
        devfreq->profile = profile;
-       devfreq->governor = governor;
+       strncpy(devfreq->governor_name, governor_name, DEVFREQ_NAME_LEN);
        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;
 
+       devfreq->trans_table =  devm_kzalloc(dev, sizeof(unsigned int) *
+                                               devfreq->profile->max_state *
+                                               devfreq->profile->max_state,
+                                               GFP_KERNEL);
+       devfreq->time_in_state = devm_kzalloc(dev, sizeof(unsigned int) *
+                                               devfreq->profile->max_state,
+                                               GFP_KERNEL);
+       devfreq->last_stat_updated = jiffies;
+
        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);
 
-       if (devfreq_wq && devfreq->next_polling && !polling) {
-               polling = true;
-               queue_delayed_work(devfreq_wq, &devfreq_work,
-                                  devfreq->next_polling);
-       }
+       governor = find_devfreq_governor(devfreq->governor_name);
+       if (!IS_ERR(governor))
+               devfreq->governor = governor;
+       if (devfreq->governor)
+               err = devfreq->governor->event_handler(devfreq,
+                                       DEVFREQ_GOV_START, NULL);
        mutex_unlock(&devfreq_list_lock);
-out:
+       if (err) {
+               dev_err(dev, "%s: Unable to start governor for the device\n",
+                       __func__);
+               goto err_init;
+       }
+
        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;
+
+       _remove_devfreq(devfreq, false);
 
+       return 0;
+}
+EXPORT_SYMBOL(devfreq_remove_device);
+
+/**
+ * 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;
 
-       central_polling = !devfreq->governor->no_central_polling;
+       if (!devfreq->governor)
+               return 0;
+
+       return devfreq->governor->event_handler(devfreq,
+                               DEVFREQ_GOV_SUSPEND, NULL);
+}
+EXPORT_SYMBOL(devfreq_suspend_device);
+
+/**
+ * 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;
+
+       if (!devfreq->governor)
+               return 0;
+
+       return devfreq->governor->event_handler(devfreq,
+                               DEVFREQ_GOV_RESUME, NULL);
+}
+EXPORT_SYMBOL(devfreq_resume_device);
+
+/**
+ * devfreq_add_governor() - Add devfreq governor
+ * @governor:  the devfreq governor to be added
+ */
+int devfreq_add_governor(struct devfreq_governor *governor)
+{
+       struct devfreq_governor *g;
+       struct devfreq *devfreq;
+       int err = 0;
+
+       if (!governor) {
+               pr_err("%s: Invalid parameters.\n", __func__);
+               return -EINVAL;
+       }
+
+       mutex_lock(&devfreq_list_lock);
+       g = find_devfreq_governor(governor->name);
+       if (!IS_ERR(g)) {
+               pr_err("%s: governor %s already registered\n", __func__,
+                      g->name);
+               err = -EINVAL;
+               goto err_out;
+       }
 
-       if (central_polling) {
-               mutex_lock(&devfreq_list_lock);
-               while (wait_remove_device == devfreq) {
-                       mutex_unlock(&devfreq_list_lock);
-                       schedule();
-                       mutex_lock(&devfreq_list_lock);
+       list_add(&governor->node, &devfreq_governor_list);
+
+       list_for_each_entry(devfreq, &devfreq_list, node) {
+               int ret = 0;
+               struct device *dev = devfreq->dev.parent;
+
+               if (!strncmp(devfreq->governor_name, governor->name,
+                            DEVFREQ_NAME_LEN)) {
+                       /* The following should never occur */
+                       if (devfreq->governor) {
+                               dev_warn(dev,
+                                        "%s: Governor %s already present\n",
+                                        __func__, devfreq->governor->name);
+                               ret = devfreq->governor->event_handler(devfreq,
+                                                       DEVFREQ_GOV_STOP, NULL);
+                               if (ret) {
+                                       dev_warn(dev,
+                                                "%s: Governor %s stop = %d\n",
+                                                __func__,
+                                                devfreq->governor->name, ret);
+                               }
+                               /* Fall through */
+                       }
+                       devfreq->governor = governor;
+                       ret = devfreq->governor->event_handler(devfreq,
+                                               DEVFREQ_GOV_START, NULL);
+                       if (ret) {
+                               dev_warn(dev, "%s: Governor %s start=%d\n",
+                                        __func__, devfreq->governor->name,
+                                        ret);
+                       }
                }
        }
 
-       mutex_lock(&devfreq->lock);
-       _remove_devfreq(devfreq, false); /* it unlocks devfreq->lock */
+err_out:
+       mutex_unlock(&devfreq_list_lock);
 
-       if (central_polling)
-               mutex_unlock(&devfreq_list_lock);
+       return err;
+}
+EXPORT_SYMBOL(devfreq_add_governor);
 
-       return 0;
+/**
+ * devfreq_remove_device() - Remove devfreq feature from a device.
+ * @governor:  the devfreq governor to be removed
+ */
+int devfreq_remove_governor(struct devfreq_governor *governor)
+{
+       struct devfreq_governor *g;
+       struct devfreq *devfreq;
+       int err = 0;
+
+       if (!governor) {
+               pr_err("%s: Invalid parameters.\n", __func__);
+               return -EINVAL;
+       }
+
+       mutex_lock(&devfreq_list_lock);
+       g = find_devfreq_governor(governor->name);
+       if (IS_ERR(g)) {
+               pr_err("%s: governor %s not registered\n", __func__,
+                      governor->name);
+               err = PTR_ERR(g);
+               goto err_out;
+       }
+       list_for_each_entry(devfreq, &devfreq_list, node) {
+               int ret;
+               struct device *dev = devfreq->dev.parent;
+
+               if (!strncmp(devfreq->governor_name, governor->name,
+                            DEVFREQ_NAME_LEN)) {
+                       /* we should have a devfreq governor! */
+                       if (!devfreq->governor) {
+                               dev_warn(dev, "%s: Governor %s NOT present\n",
+                                        __func__, governor->name);
+                               continue;
+                               /* Fall through */
+                       }
+                       ret = devfreq->governor->event_handler(devfreq,
+                                               DEVFREQ_GOV_STOP, NULL);
+                       if (ret) {
+                               dev_warn(dev, "%s: Governor %s stop=%d\n",
+                                        __func__, devfreq->governor->name,
+                                        ret);
+                       }
+                       devfreq->governor = NULL;
+               }
+       }
+
+       list_del(&governor->node);
+err_out:
+       mutex_unlock(&devfreq_list_lock);
+
+       return err;
 }
+EXPORT_SYMBOL(devfreq_remove_governor);
 
 static ssize_t show_governor(struct device *dev,
                             struct device_attribute *attr, char *buf)
 {
+       if (!to_devfreq(dev)->governor)
+               return -EINVAL;
+
        return sprintf(buf, "%s\n", to_devfreq(dev)->governor->name);
 }
 
+static ssize_t store_governor(struct device *dev, struct device_attribute *attr,
+                             const char *buf, size_t count)
+{
+       struct devfreq *df = to_devfreq(dev);
+       int ret;
+       char str_governor[DEVFREQ_NAME_LEN + 1];
+       struct devfreq_governor *governor;
+
+       ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor);
+       if (ret != 1)
+               return -EINVAL;
+
+       mutex_lock(&devfreq_list_lock);
+       governor = find_devfreq_governor(str_governor);
+       if (IS_ERR(governor)) {
+               ret = PTR_ERR(governor);
+               goto out;
+       }
+       if (df->governor == governor)
+               goto out;
+
+       if (df->governor) {
+               ret = df->governor->event_handler(df, DEVFREQ_GOV_STOP, NULL);
+               if (ret) {
+                       dev_warn(dev, "%s: Governor %s not stopped(%d)\n",
+                                __func__, df->governor->name, ret);
+                       goto out;
+               }
+       }
+       df->governor = governor;
+       strncpy(df->governor_name, governor->name, DEVFREQ_NAME_LEN);
+       ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
+       if (ret)
+               dev_warn(dev, "%s: Governor %s not started(%d)\n",
+                        __func__, df->governor->name, ret);
+out:
+       mutex_unlock(&devfreq_list_lock);
+
+       if (!ret)
+               ret = count;
+       return ret;
+}
+static ssize_t show_available_governors(struct device *d,
+                                   struct device_attribute *attr,
+                                   char *buf)
+{
+       struct devfreq_governor *tmp_governor;
+       ssize_t count = 0;
+
+       mutex_lock(&devfreq_list_lock);
+       list_for_each_entry(tmp_governor, &devfreq_governor_list, node)
+               count += scnprintf(&buf[count], (PAGE_SIZE - count - 2),
+                                  "%s ", tmp_governor->name);
+       mutex_unlock(&devfreq_list_lock);
+
+       /* Truncate the trailing space */
+       if (count)
+               count--;
+
+       count += sprintf(&buf[count], "\n");
+
+       return count;
+}
+
 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);
 }
 
@@ -486,39 +790,19 @@ static ssize_t store_polling_interval(struct device *dev,
        unsigned int value;
        int ret;
 
+       if (!df->governor)
+               return -EINVAL;
+
        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 +813,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 +827,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 +846,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 +860,6 @@ static ssize_t store_max_freq(struct device *dev, struct device_attribute *attr,
        ret = count;
 unlock:
        mutex_unlock(&df->lock);
-out:
        return ret;
 }
 
@@ -587,34 +869,92 @@ static ssize_t show_max_freq(struct device *dev, struct device_attribute *attr,
        return sprintf(buf, "%lu\n", to_devfreq(dev)->max_freq);
 }
 
+static ssize_t show_available_freqs(struct device *d,
+                                   struct device_attribute *attr,
+                                   char *buf)
+{
+       struct devfreq *df = to_devfreq(d);
+       struct device *dev = df->dev.parent;
+       struct opp *opp;
+       ssize_t count = 0;
+       unsigned long freq = 0;
+
+       rcu_read_lock();
+       do {
+               opp = opp_find_freq_ceil(dev, &freq);
+               if (IS_ERR(opp))
+                       break;
+
+               count += scnprintf(&buf[count], (PAGE_SIZE - count - 2),
+                                  "%lu ", freq);
+               freq++;
+       } while (1);
+       rcu_read_unlock();
+
+       /* Truncate the trailing space */
+       if (count)
+               count--;
+
+       count += sprintf(&buf[count], "\n");
+
+       return count;
+}
+
+static ssize_t show_trans_table(struct device *dev, struct device_attribute *attr,
+                               char *buf)
+{
+       struct devfreq *devfreq = to_devfreq(dev);
+       ssize_t len;
+       int i, j, err;
+       unsigned int max_state = devfreq->profile->max_state;
+
+       err = devfreq_update_status(devfreq, devfreq->previous_freq);
+       if (err)
+               return 0;
+
+       len = sprintf(buf, "   From  :   To\n");
+       len += sprintf(buf + len, "         :");
+       for (i = 0; i < max_state; i++)
+               len += sprintf(buf + len, "%8u",
+                               devfreq->profile->freq_table[i]);
+
+       len += sprintf(buf + len, "   time(ms)\n");
+
+       for (i = 0; i < max_state; i++) {
+               if (devfreq->profile->freq_table[i]
+                                       == devfreq->previous_freq) {
+                       len += sprintf(buf + len, "*");
+               } else {
+                       len += sprintf(buf + len, " ");
+               }
+               len += sprintf(buf + len, "%8u:",
+                               devfreq->profile->freq_table[i]);
+               for (j = 0; j < max_state; j++)
+                       len += sprintf(buf + len, "%8u",
+                               devfreq->trans_table[(i * max_state) + j]);
+               len += sprintf(buf + len, "%10u\n",
+                       jiffies_to_msecs(devfreq->time_in_state[i]));
+       }
+
+       len += sprintf(buf + len, "Total transition : %u\n",
+                                       devfreq->total_trans);
+       return len;
+}
+
 static struct device_attribute devfreq_attrs[] = {
-       __ATTR(governor, S_IRUGO, show_governor, NULL),
+       __ATTR(governor, S_IRUGO | S_IWUSR, show_governor, store_governor),
+       __ATTR(available_governors, S_IRUGO, show_available_governors, NULL),
        __ATTR(cur_freq, S_IRUGO, show_freq, NULL),
-       __ATTR(central_polling, S_IRUGO, show_central_polling, NULL),
+       __ATTR(available_frequencies, S_IRUGO, show_available_freqs, 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),
        __ATTR(max_freq, S_IRUGO | S_IWUSR, show_max_freq, store_max_freq),
+       __ATTR(trans_stat, S_IRUGO, show_trans_table, NULL),
        { },
 };
 
-/**
- * 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 +962,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 +978,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 +990,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 +1005,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,35 +1023,49 @@ 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)
 {
-       struct srcu_notifier_head *nh = opp_get_notifier(dev);
+       struct srcu_notifier_head *nh;
+       int ret = 0;
 
+       rcu_read_lock();
+       nh = opp_get_notifier(dev);
        if (IS_ERR(nh))
-               return PTR_ERR(nh);
-       return srcu_notifier_chain_register(nh, &devfreq->nb);
+               ret = PTR_ERR(nh);
+       rcu_read_unlock();
+       if (!ret)
+               ret = srcu_notifier_chain_register(nh, &devfreq->nb);
+
+       return ret;
 }
 
 /**
  * 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.
  */
 int devfreq_unregister_opp_notifier(struct device *dev, struct devfreq *devfreq)
 {
-       struct srcu_notifier_head *nh = opp_get_notifier(dev);
+       struct srcu_notifier_head *nh;
+       int ret = 0;
 
+       rcu_read_lock();
+       nh = opp_get_notifier(dev);
        if (IS_ERR(nh))
-               return PTR_ERR(nh);
-       return srcu_notifier_chain_unregister(nh, &devfreq->nb);
+               ret = PTR_ERR(nh);
+       rcu_read_unlock();
+       if (!ret)
+               ret = srcu_notifier_chain_unregister(nh, &devfreq->nb);
+
+       return ret;
 }
 
 MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
index 88ddc77..7418372 100644 (file)
@@ -987,7 +987,7 @@ static __devinit int exynos4_busfreq_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        int err = 0;
 
-       data = kzalloc(sizeof(struct busfreq_data), GFP_KERNEL);
+       data = devm_kzalloc(&pdev->dev, sizeof(struct busfreq_data), GFP_KERNEL);
        if (data == NULL) {
                dev_err(dev, "Cannot allocate memory.\n");
                return -ENOMEM;
@@ -1012,31 +1012,26 @@ static __devinit int exynos4_busfreq_probe(struct platform_device *pdev)
                err = -EINVAL;
        }
        if (err)
-               goto err_regulator;
+               return err;
 
-       data->vdd_int = regulator_get(dev, "vdd_int");
+       data->vdd_int = devm_regulator_get(dev, "vdd_int");
        if (IS_ERR(data->vdd_int)) {
                dev_err(dev, "Cannot get the regulator \"vdd_int\"\n");
-               err = PTR_ERR(data->vdd_int);
-               goto err_regulator;
+               return PTR_ERR(data->vdd_int);
        }
        if (data->type == TYPE_BUSF_EXYNOS4x12) {
-               data->vdd_mif = regulator_get(dev, "vdd_mif");
+               data->vdd_mif = devm_regulator_get(dev, "vdd_mif");
                if (IS_ERR(data->vdd_mif)) {
                        dev_err(dev, "Cannot get the regulator \"vdd_mif\"\n");
-                       err = PTR_ERR(data->vdd_mif);
-                       regulator_put(data->vdd_int);
-                       goto err_regulator;
-
+                       return PTR_ERR(data->vdd_mif);
                }
        }
 
        opp = opp_find_freq_floor(dev, &exynos4_devfreq_profile.initial_freq);
        if (IS_ERR(opp)) {
                dev_err(dev, "Invalid initial frequency %lu kHz.\n",
-                      exynos4_devfreq_profile.initial_freq);
-               err = PTR_ERR(opp);
-               goto err_opp_add;
+                       exynos4_devfreq_profile.initial_freq);
+               return PTR_ERR(opp);
        }
        data->curr_opp = opp;
 
@@ -1045,30 +1040,20 @@ static __devinit int exynos4_busfreq_probe(struct platform_device *pdev)
        busfreq_mon_reset(data);
 
        data->devfreq = devfreq_add_device(dev, &exynos4_devfreq_profile,
-                                          &devfreq_simple_ondemand, NULL);
-       if (IS_ERR(data->devfreq)) {
-               err = PTR_ERR(data->devfreq);
-               goto err_opp_add;
-       }
+                                          "simple_ondemand", NULL);
+       if (IS_ERR(data->devfreq))
+               return PTR_ERR(data->devfreq);
 
        devfreq_register_opp_notifier(dev, data->devfreq);
 
        err = register_pm_notifier(&data->pm_notifier);
        if (err) {
                dev_err(dev, "Failed to setup pm notifier\n");
-               goto err_devfreq_add;
+               devfreq_remove_device(data->devfreq);
+               return err;
        }
 
        return 0;
-err_devfreq_add:
-       devfreq_remove_device(data->devfreq);
-err_opp_add:
-       if (data->vdd_mif)
-               regulator_put(data->vdd_mif);
-       regulator_put(data->vdd_int);
-err_regulator:
-       kfree(data);
-       return err;
 }
 
 static __devexit int exynos4_busfreq_remove(struct platform_device *pdev)
@@ -1077,10 +1062,6 @@ static __devexit int exynos4_busfreq_remove(struct platform_device *pdev)
 
        unregister_pm_notifier(&data->pm_notifier);
        devfreq_remove_device(data->devfreq);
-       regulator_put(data->vdd_int);
-       if (data->vdd_mif)
-               regulator_put(data->vdd_mif);
-       kfree(data);
 
        return 0;
 }
index ea7f13c..fad7d63 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);
+
+extern int devfreq_add_governor(struct devfreq_governor *governor);
+extern int devfreq_remove_governor(struct devfreq_governor *governor);
+
 #endif /* _GOVERNOR_H */
index af75ddd..c72f942 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <linux/devfreq.h>
+#include <linux/module.h>
 #include "governor.h"
 
 static int devfreq_performance_func(struct devfreq *df,
@@ -26,14 +27,41 @@ 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 = {
+static 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,
 };
+
+static int __init devfreq_performance_init(void)
+{
+       return devfreq_add_governor(&devfreq_performance);
+}
+subsys_initcall(devfreq_performance_init);
+
+static void __exit devfreq_performance_exit(void)
+{
+       int ret;
+
+       ret = devfreq_remove_governor(&devfreq_performance);
+       if (ret)
+               pr_err("%s: failed remove governor %d\n", __func__, ret);
+
+       return;
+}
+module_exit(devfreq_performance_exit);
+MODULE_LICENSE("GPL");
index fec0cdb..0c6bed5 100644 (file)
@@ -10,6 +10,7 @@
  */
 
 #include <linux/devfreq.h>
+#include <linux/module.h>
 #include "governor.h"
 
 static int devfreq_powersave_func(struct devfreq *df,
@@ -23,14 +24,41 @@ 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 = {
+static 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,
 };
+
+static int __init devfreq_powersave_init(void)
+{
+       return devfreq_add_governor(&devfreq_powersave);
+}
+subsys_initcall(devfreq_powersave_init);
+
+static void __exit devfreq_powersave_exit(void)
+{
+       int ret;
+
+       ret = devfreq_remove_governor(&devfreq_powersave);
+       if (ret)
+               pr_err("%s: failed remove governor %d\n", __func__, ret);
+
+       return;
+}
+module_exit(devfreq_powersave_exit);
+MODULE_LICENSE("GPL");
index a2e3eae..0720ba8 100644 (file)
  */
 
 #include <linux/errno.h>
+#include <linux/module.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 +90,58 @@ static int devfreq_simple_ondemand_func(struct devfreq *df,
        return 0;
 }
 
-const struct devfreq_governor devfreq_simple_ondemand = {
+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;
+}
+
+static struct devfreq_governor devfreq_simple_ondemand = {
        .name = "simple_ondemand",
        .get_target_freq = devfreq_simple_ondemand_func,
+       .event_handler = devfreq_simple_ondemand_handler,
 };
+
+static int __init devfreq_simple_ondemand_init(void)
+{
+       return devfreq_add_governor(&devfreq_simple_ondemand);
+}
+subsys_initcall(devfreq_simple_ondemand_init);
+
+static void __exit devfreq_simple_ondemand_exit(void)
+{
+       int ret;
+
+       ret = devfreq_remove_governor(&devfreq_simple_ondemand);
+       if (ret)
+               pr_err("%s: failed remove governor %d\n", __func__, ret);
+
+       return;
+}
+module_exit(devfreq_simple_ondemand_exit);
+MODULE_LICENSE("GPL");
index 0681246..35de6e8 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/devfreq.h>
 #include <linux/pm.h>
 #include <linux/mutex.h>
+#include <linux/module.h>
 #include "governor.h"
 
 struct userspace_data {
@@ -116,10 +117,46 @@ static void userspace_exit(struct devfreq *devfreq)
        devfreq->data = NULL;
 }
 
-const struct devfreq_governor devfreq_userspace = {
+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;
+}
+
+static 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,
 };
+
+static int __init devfreq_userspace_init(void)
+{
+       return devfreq_add_governor(&devfreq_userspace);
+}
+subsys_initcall(devfreq_userspace_init);
+
+static void __exit devfreq_userspace_exit(void)
+{
+       int ret;
+
+       ret = devfreq_remove_governor(&devfreq_userspace);
+       if (ret)
+               pr_err("%s: failed remove governor %d\n", __func__, ret);
+
+       return;
+}
+module_exit(devfreq_userspace_exit);
+MODULE_LICENSE("GPL");
index 677cd6e..d4c1218 100644 (file)
@@ -90,6 +90,17 @@ config DW_DMAC
          Support the Synopsys DesignWare AHB DMA controller.  This
          can be integrated in chips such as the Atmel AT32ap7000.
 
+config DW_DMAC_BIG_ENDIAN_IO
+       bool "Use big endian I/O register access"
+       default y if AVR32
+       depends on DW_DMAC
+       help
+         Say yes here to use big endian I/O access when reading and writing
+         to the DMA controller registers. This is needed on some platforms,
+         like the Atmel AVR32 architecture.
+
+         If unsure, use the default setting.
+
 config AT_HDMAC
        tristate "Atmel AHB DMA support"
        depends on ARCH_AT91
index ff39fa6..8896559 100644 (file)
@@ -98,9 +98,17 @@ struct dw_dma_regs {
        u32     DW_PARAMS;
 };
 
+#ifdef CONFIG_DW_DMAC_BIG_ENDIAN_IO
+#define dma_readl_native ioread32be
+#define dma_writel_native iowrite32be
+#else
+#define dma_readl_native readl
+#define dma_writel_native writel
+#endif
+
 /* To access the registers in early stage of probe */
 #define dma_read_byaddr(addr, name) \
-       readl((addr) + offsetof(struct dw_dma_regs, name))
+       dma_readl_native((addr) + offsetof(struct dw_dma_regs, name))
 
 /* Bitfields in DW_PARAMS */
 #define DW_PARAMS_NR_CHAN      8               /* number of channels */
@@ -216,9 +224,9 @@ __dwc_regs(struct dw_dma_chan *dwc)
 }
 
 #define channel_readl(dwc, name) \
-       readl(&(__dwc_regs(dwc)->name))
+       dma_readl_native(&(__dwc_regs(dwc)->name))
 #define channel_writel(dwc, name, val) \
-       writel((val), &(__dwc_regs(dwc)->name))
+       dma_writel_native((val), &(__dwc_regs(dwc)->name))
 
 static inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan)
 {
@@ -246,9 +254,9 @@ static inline struct dw_dma_regs __iomem *__dw_regs(struct dw_dma *dw)
 }
 
 #define dma_readl(dw, name) \
-       readl(&(__dw_regs(dw)->name))
+       dma_readl_native(&(__dw_regs(dw)->name))
 #define dma_writel(dw, name, val) \
-       writel((val), &(__dw_regs(dw)->name))
+       dma_writel_native((val), &(__dw_regs(dw)->name))
 
 #define channel_set_bit(dw, reg, mask) \
        dma_writel(dw, reg, ((mask) << 8) | (mask))
index f11b5b2..7d9554c 100644 (file)
@@ -474,8 +474,10 @@ static int imxdma_xfer_desc(struct imxdma_desc *d)
                        slot = i;
                        break;
                }
-               if (slot < 0)
+               if (slot < 0) {
+                       spin_unlock_irqrestore(&imxdma->lock, flags);
                        return -EBUSY;
+               }
 
                imxdma->slots_2d[slot].xsr = d->x;
                imxdma->slots_2d[slot].ysr = d->y;
index 64385cd..d451caa 100644 (file)
@@ -109,7 +109,7 @@ static void sirfsoc_dma_execute(struct sirfsoc_dma_chan *schan)
        sdesc = list_first_entry(&schan->queued, struct sirfsoc_dma_desc,
                node);
        /* Move the first queued descriptor to active list */
-       list_move_tail(&schan->queued, &schan->active);
+       list_move_tail(&sdesc->node, &schan->active);
 
        /* Start the DMA transfer */
        writel_relaxed(sdesc->width, sdma->base + SIRFSOC_DMA_WIDTH_0 +
@@ -428,7 +428,7 @@ static struct dma_async_tx_descriptor *sirfsoc_dma_prep_interleaved(
        unsigned long iflags;
        int ret;
 
-       if ((xt->dir != DMA_MEM_TO_DEV) || (xt->dir != DMA_DEV_TO_MEM)) {
+       if ((xt->dir != DMA_MEM_TO_DEV) && (xt->dir != DMA_DEV_TO_MEM)) {
                ret = -EINVAL;
                goto err_dir;
        }
index 409b92b..bb82d6b 100644 (file)
@@ -42,10 +42,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)"
index 5a297a2..f74a684 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 8d48047..e864f40 100644 (file)
@@ -33,7 +33,7 @@
  *             detection. The mods to Rev F required more family
  *             information detection.
  *
- *     Changes/Fixes by Borislav Petkov <borislav.petkov@amd.com>:
+ *     Changes/Fixes by Borislav Petkov <bp@alien8.de>:
  *             - misc fixes and code cleanups
  *
  * This module is based on the following documents
 #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 53d972e..8c171fa 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 90f0b73..281f566 100644 (file)
@@ -416,10 +416,18 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
                dimm->cschannel = chn;
 
                /* Increment csrow location */
-               row++;
-               if (row == tot_csrows) {
-                       row = 0;
+               if (layers[0].is_virt_csrow) {
                        chn++;
+                       if (chn == tot_channels) {
+                               chn = 0;
+                               row++;
+                       }
+               } else {
+                       row++;
+                       if (row == tot_csrows) {
+                               row = 0;
+                               chn++;
+                       }
                }
 
                /* Increment dimm location */
@@ -966,20 +974,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 +1024,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 +1107,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 +1138,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];
 
@@ -1195,6 +1206,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 +1219,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 ed0bc07..de2df92 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,
 };
@@ -1124,10 +1126,15 @@ int __init edac_mc_sysfs_init(void)
        edac_subsys = edac_get_sysfs_subsys();
        if (edac_subsys == NULL) {
                edac_dbg(1, "no edac_subsys\n");
-               return -EINVAL;
+               err = -EINVAL;
+               goto out;
        }
 
        mci_pdev = kzalloc(sizeof(*mci_pdev), GFP_KERNEL);
+       if (!mci_pdev) {
+               err = -ENOMEM;
+               goto out_put_sysfs;
+       }
 
        mci_pdev->bus = edac_subsys;
        mci_pdev->type = &mc_attr_type;
@@ -1136,11 +1143,18 @@ int __init edac_mc_sysfs_init(void)
 
        err = device_add(mci_pdev);
        if (err < 0)
-               return err;
+               goto out_dev_free;
 
        edac_dbg(0, "device %s created\n", dev_name(mci_pdev));
 
        return 0;
+
+ out_dev_free:
+       kfree(mci_pdev);
+ out_put_sysfs:
+       edac_put_sysfs_subsys();
+ out:
+       return err;
 }
 
 void __exit edac_mc_sysfs_exit(void)
@@ -1148,4 +1162,5 @@ void __exit edac_mc_sysfs_exit(void)
        put_device(mci_pdev);
        device_del(mci_pdev);
        edac_put_sysfs_subsys();
+       kfree(mci_pdev);
 }
index 58a28d8..12c951a 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 ee87ef9..dd370f9 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 e164c55..dc6e905 100644 (file)
@@ -645,20 +645,16 @@ typedef void (*pci_parity_check_fn_t) (struct pci_dev *dev);
 
 /*
  * pci_dev parity list iterator
- *     Scan the PCI device list for one pass, looking for SERRORs
- *     Master Parity ERRORS or Parity ERRORs on primary or secondary devices
+ *
+ *     Scan the PCI device list looking for SERRORs, Master Parity ERRORS or
+ *     Parity ERRORs on primary or secondary devices.
  */
 static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn)
 {
        struct pci_dev *dev = NULL;
 
-       /* request for kernel access to the next PCI device, if any,
-        * and while we are looking at it have its reference count
-        * bumped until we are done with it
-        */
-       while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+       for_each_pci_dev(dev)
                fn(dev);
-       }
 }
 
 /*
index 6c86f6e..351945f 100644 (file)
@@ -5,7 +5,7 @@
  *
  * 2007 (c) MontaVista Software, Inc.
  * 2010 (c) Advanced Micro Devices Inc.
- *         Borislav Petkov <borislav.petkov@amd.com>
+ *         Borislav Petkov <bp@alien8.de>
  *
  * This file is licensed under the terms of the GNU General Public
  * License version 2. This program is licensed "as is" without any
index c769f47..7ea4cc2 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 a09d066..9d669cd 100644 (file)
@@ -197,8 +197,8 @@ static const char *ferr_fat_fbd_name[] = {
        [0]  = "Memory Write error on non-redundant retry or "
               "FBD configuration Write error on retry",
 };
-#define GET_FBD_FAT_IDX(fbderr)        (fbderr & (3 << 28))
-#define FERR_FAT_FBD_ERR_MASK ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3))
+#define GET_FBD_FAT_IDX(fbderr)        (((fbderr) >> 28) & 3)
+#define FERR_FAT_FBD_ERR_MASK ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 22))
 
 #define FERR_NF_FBD    0xa0
 static const char *ferr_nf_fbd_name[] = {
@@ -225,7 +225,7 @@ static const char *ferr_nf_fbd_name[] = {
        [1]  = "Aliased Uncorrectable Non-Mirrored Demand Data ECC",
        [0]  = "Uncorrectable Data ECC on Replay",
 };
-#define GET_FBD_NF_IDX(fbderr) (fbderr & (3 << 28))
+#define GET_FBD_NF_IDX(fbderr) (((fbderr) >> 28) & 3)
 #define FERR_NF_FBD_ERR_MASK ((1 << 24) | (1 << 23) | (1 << 22) | (1 << 21) |\
                              (1 << 18) | (1 << 17) | (1 << 16) | (1 << 15) |\
                              (1 << 14) | (1 << 13) | (1 << 11) | (1 << 10) |\
@@ -464,7 +464,7 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci)
                errnum = find_first_bit(&errors,
                                        ARRAY_SIZE(ferr_nf_fbd_name));
                specific = GET_ERR_FROM_TABLE(ferr_nf_fbd_name, errnum);
-               branch = (GET_FBD_FAT_IDX(error_reg) == 2) ? 1 : 0;
+               branch = (GET_FBD_NF_IDX(error_reg) == 2) ? 1 : 0;
 
                pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
                        REDMEMA, &syndrome);
index 3672101..10c8c00 100644 (file)
@@ -816,7 +816,7 @@ static ssize_t i7core_inject_store_##param(                 \
        struct device_attribute *mattr,                         \
        const char *data, size_t count)                         \
 {                                                              \
-       struct mem_ctl_info *mci = to_mci(dev);                 \
+       struct mem_ctl_info *mci = dev_get_drvdata(dev);        \
        struct i7core_pvt *pvt;                                 \
        long value;                                             \
        int rc;                                                 \
@@ -845,7 +845,7 @@ static ssize_t i7core_inject_show_##param(                  \
        struct device_attribute *mattr,                         \
        char *data)                                             \
 {                                                              \
-       struct mem_ctl_info *mci = to_mci(dev);                 \
+       struct mem_ctl_info *mci = dev_get_drvdata(dev);        \
        struct i7core_pvt *pvt;                                 \
                                                                \
        pvt = mci->pvt_info;                                    \
@@ -1052,7 +1052,7 @@ static ssize_t i7core_show_counter_##param(                       \
        struct device_attribute *mattr,                         \
        char *data)                                             \
 {                                                              \
-       struct mem_ctl_info *mci = to_mci(dev);                 \
+       struct mem_ctl_info *mci = dev_get_drvdata(dev);        \
        struct i7core_pvt *pvt = mci->pvt_info;                 \
                                                                \
        edac_dbg(1, "\n");                                      \
index 069e26c..a980204 100644 (file)
@@ -370,10 +370,6 @@ static enum dev_type i82975x_dram_type(void __iomem *mch_window, int rank)
 static void i82975x_init_csrows(struct mem_ctl_info *mci,
                struct pci_dev *pdev, void __iomem *mch_window)
 {
-       static const char *labels[4] = {
-                                                       "DIMM A1", "DIMM A2",
-                                                       "DIMM B1", "DIMM B2"
-                                               };
        struct csrow_info *csrow;
        unsigned long last_cumul_size;
        u8 value;
@@ -423,9 +419,10 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci,
                        dimm = mci->csrows[index]->channels[chan]->dimm;
 
                        dimm->nr_pages = nr_pages / csrow->nr_channels;
-                       strncpy(csrow->channels[chan]->dimm->label,
-                                       labels[(index >> 1) + (chan * 2)],
-                                       EDAC_MC_LABEL_LEN);
+
+                       snprintf(csrow->channels[chan]->dimm->label, EDAC_MC_LABEL_LEN, "DIMM %c%d",
+                                (chan == 0) ? 'A' : 'B',
+                                index);
                        dimm->grain = 1 << 7;   /* 128Byte cache-line resolution */
                        dimm->dtype = i82975x_dram_type(mch_window, index);
                        dimm->mtype = MEM_DDR2; /* I82975x supports only DDR2 */
index d0c372e..ad63757 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 8c87a5e..6796799 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 */
index 66b5151..2ae78f2 100644 (file)
@@ -6,7 +6,7 @@
  * This file may be distributed under the terms of the GNU General Public
  * License version 2.
  *
- * Copyright (c) 2010:  Borislav Petkov <borislav.petkov@amd.com>
+ * Copyright (c) 2010:  Borislav Petkov <bp@alien8.de>
  *                     Advanced Micro Devices Inc.
  */
 
@@ -168,6 +168,6 @@ module_init(edac_init_mce_inject);
 module_exit(edac_exit_mce_inject);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Borislav Petkov <borislav.petkov@amd.com>");
+MODULE_AUTHOR("Borislav Petkov <bp@alien8.de>");
 MODULE_AUTHOR("AMD Inc.");
 MODULE_DESCRIPTION("MCE injection facility for testing MCE decoding");
index 725eb5a..e87196f 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 946a318..d398821 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 3cc152e..71d3ab7 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 e21387e..a17d0d9 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 ef9090a..77b66b0 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 1162d6b..bb1b392 100644 (file)
@@ -1546,6 +1546,8 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
        struct sbp2_logical_unit *lu = sdev->hostdata;
 
        sdev->use_10_for_rw = 1;
+       sdev->no_report_opcodes = 1;
+       sdev->no_write_same = 1;
 
        if (sbp2_param_exclusive_login)
                sdev->manage_start_stop = 1;
index c1cdc92..90723e6 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 39d9323..14a6c29 100644 (file)
@@ -47,7 +47,11 @@ if GPIOLIB
 
 config OF_GPIO
        def_bool y
-       depends on OF && !SPARC
+       depends on OF
+
+config GPIO_ACPI
+       def_bool y
+       depends on ACPI
 
 config DEBUG_GPIO
        bool "Debug GPIO calls"
@@ -496,7 +500,7 @@ config GPIO_ADP5588_IRQ
 
 config GPIO_ADNP
        tristate "Avionic Design N-bit GPIO expander"
-       depends on I2C && OF
+       depends on I2C && OF_GPIO
        help
          This option enables support for N GPIOs found on Avionic Design
          I2C GPIO expanders. The register space will be extended by powers
index a41c250..76b3446 100644 (file)
@@ -4,6 +4,7 @@ ccflags-$(CONFIG_DEBUG_GPIO)    += -DDEBUG
 
 obj-$(CONFIG_GPIOLIB)          += gpiolib.o devres.o
 obj-$(CONFIG_OF_GPIO)          += gpiolib-of.o
+obj-$(CONFIG_GPIO_ACPI)                += gpiolib-acpi.o
 
 # Device drivers. Generally keep list sorted alphabetically
 obj-$(CONFIG_GPIO_GENERIC)     += gpio-generic.o
index ed3e551..f05e542 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;
index 0f42518..ce1c847 100644 (file)
@@ -77,7 +77,7 @@ struct mcp23s08_driver_data {
 
 /*----------------------------------------------------------------------*/
 
-#ifdef CONFIG_I2C
+#if IS_ENABLED(CONFIG_I2C)
 
 static int mcp23008_read(struct mcp23s08 *mcp, unsigned reg)
 {
@@ -399,7 +399,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
                break;
 #endif /* CONFIG_SPI_MASTER */
 
-#ifdef CONFIG_I2C
+#if IS_ENABLED(CONFIG_I2C)
        case MCP_TYPE_008:
                mcp->ops = &mcp23008_ops;
                mcp->chip.ngpio = 8;
@@ -473,7 +473,7 @@ fail:
 
 /*----------------------------------------------------------------------*/
 
-#ifdef CONFIG_I2C
+#if IS_ENABLED(CONFIG_I2C)
 
 static int __devinit mcp230xx_probe(struct i2c_client *client,
                                    const struct i2c_device_id *id)
index 8b30657..a515b92 100644 (file)
@@ -92,6 +92,11 @@ static inline void __iomem *mvebu_gpioreg_out(struct mvebu_gpio_chip *mvchip)
        return mvchip->membase + GPIO_OUT_OFF;
 }
 
+static inline void __iomem *mvebu_gpioreg_blink(struct mvebu_gpio_chip *mvchip)
+{
+       return mvchip->membase + GPIO_BLINK_EN_OFF;
+}
+
 static inline void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip)
 {
        return mvchip->membase + GPIO_IO_CONF_OFF;
@@ -206,6 +211,23 @@ static int mvebu_gpio_get(struct gpio_chip *chip, unsigned pin)
        return (u >> pin) & 1;
 }
 
+static void mvebu_gpio_blink(struct gpio_chip *chip, unsigned pin, int value)
+{
+       struct mvebu_gpio_chip *mvchip =
+               container_of(chip, struct mvebu_gpio_chip, chip);
+       unsigned long flags;
+       u32 u;
+
+       spin_lock_irqsave(&mvchip->lock, flags);
+       u = readl_relaxed(mvebu_gpioreg_blink(mvchip));
+       if (value)
+               u |= 1 << pin;
+       else
+               u &= ~(1 << pin);
+       writel_relaxed(u, mvebu_gpioreg_blink(mvchip));
+       spin_unlock_irqrestore(&mvchip->lock, flags);
+}
+
 static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned pin)
 {
        struct mvebu_gpio_chip *mvchip =
@@ -244,6 +266,9 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
        if (ret)
                return ret;
 
+       mvebu_gpio_blink(chip, pin, 0);
+       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 +406,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 +428,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;
@@ -642,7 +670,7 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
        ct->handler = handle_edge_irq;
        ct->chip.name = mvchip->chip.label;
 
-       irq_setup_generic_chip(gc, IRQ_MSK(ngpios), IRQ_GC_INIT_MASK_CACHE,
+       irq_setup_generic_chip(gc, IRQ_MSK(ngpios), 0,
                               IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
 
        /* Setup irq domain on top of the generic chip. */
index eb73dee..d71e5bd 100644 (file)
@@ -251,6 +251,40 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
        }
 }
 
+/**
+ * _clear_gpio_debounce - clear debounce settings for a gpio
+ * @bank: the gpio bank we're acting upon
+ * @gpio: the gpio number on this @gpio
+ *
+ * If a gpio is using debounce, then clear the debounce enable bit and if
+ * this is the only gpio in this bank using debounce, then clear the debounce
+ * time too. The debounce clock will also be disabled when calling this function
+ * if this is the only gpio in the bank using debounce.
+ */
+static void _clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio)
+{
+       u32 gpio_bit = GPIO_BIT(bank, gpio);
+
+       if (!bank->dbck_flag)
+               return;
+
+       if (!(bank->dbck_enable_mask & gpio_bit))
+               return;
+
+       bank->dbck_enable_mask &= ~gpio_bit;
+       bank->context.debounce_en &= ~gpio_bit;
+       __raw_writel(bank->context.debounce_en,
+                    bank->base + bank->regs->debounce_en);
+
+       if (!bank->dbck_enable_mask) {
+               bank->context.debounce = 0;
+               __raw_writel(bank->context.debounce, bank->base +
+                            bank->regs->debounce);
+               clk_disable(bank->dbck);
+               bank->dbck_enabled = false;
+       }
+}
+
 static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,
                                                unsigned trigger)
 {
@@ -539,6 +573,7 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio)
        _set_gpio_irqenable(bank, gpio, 0);
        _clear_gpio_irqstatus(bank, gpio);
        _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
+       _clear_gpio_debounce(bank, gpio);
 }
 
 /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
index 031c6ad..1a3e2b9 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);
 }
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
new file mode 100644 (file)
index 0000000..cbad6e9
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * ACPI helpers for GPIO API
+ *
+ * Copyright (C) 2012, Intel Corporation
+ * Authors: Mathias Nyman <mathias.nyman@linux.intel.com>
+ *          Mika Westerberg <mika.westerberg@linux.intel.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/errno.h>
+#include <linux/gpio.h>
+#include <linux/export.h>
+#include <linux/acpi_gpio.h>
+#include <linux/acpi.h>
+
+static int acpi_gpiochip_find(struct gpio_chip *gc, void *data)
+{
+       if (!gc->dev)
+               return false;
+
+       return ACPI_HANDLE(gc->dev) == data;
+}
+
+/**
+ * acpi_get_gpio() - Translate ACPI GPIO pin to GPIO number usable with GPIO API
+ * @path:      ACPI GPIO controller full path name, (e.g. "\\_SB.GPO1")
+ * @pin:       ACPI GPIO pin number (0-based, controller-relative)
+ *
+ * Returns GPIO number to use with Linux generic GPIO API, or errno error value
+ */
+
+int acpi_get_gpio(char *path, int pin)
+{
+       struct gpio_chip *chip;
+       acpi_handle handle;
+       acpi_status status;
+
+       status = acpi_get_handle(NULL, path, &handle);
+       if (ACPI_FAILURE(status))
+               return -ENODEV;
+
+       chip = gpiochip_find(handle, acpi_gpiochip_find);
+       if (!chip)
+               return -ENODEV;
+
+       if (!gpio_is_valid(chip->base + pin))
+               return -EINVAL;
+
+       return chip->base + pin;
+}
+EXPORT_SYMBOL_GPL(acpi_get_gpio);
index f1a4599..d542a14 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_gpio.h>
+#include <linux/pinctrl/pinctrl.h>
 #include <linux/slab.h>
 
 /* Private data structure for of_gpiochip_find_and_xlate */
@@ -216,6 +217,54 @@ err0:
 }
 EXPORT_SYMBOL(of_mm_gpiochip_add);
 
+#ifdef CONFIG_PINCTRL
+static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
+{
+       struct device_node *np = chip->of_node;
+       struct of_phandle_args pinspec;
+       struct pinctrl_dev *pctldev;
+       int index = 0, ret;
+
+       if (!np)
+               return;
+
+       do {
+               ret = of_parse_phandle_with_args(np, "gpio-ranges",
+                               "#gpio-range-cells", index, &pinspec);
+               if (ret)
+                       break;
+
+               pctldev = of_pinctrl_get(pinspec.np);
+               if (!pctldev)
+                       break;
+
+               /*
+                * This assumes that the n GPIO pins are consecutive in the
+                * GPIO number space, and that the pins are also consecutive
+                * in their local number space. Currently it is not possible
+                * to add different ranges for one and the same GPIO chip,
+                * as the code assumes that we have one consecutive range
+                * on both, mapping 1-to-1.
+                *
+                * TODO: make the OF bindings handle multiple sparse ranges
+                * on the same GPIO chip.
+                */
+               ret = gpiochip_add_pin_range(chip,
+                                            pinctrl_dev_get_name(pctldev),
+                                            0, /* offset in gpiochip */
+                                            pinspec.args[0],
+                                            pinspec.args[1]);
+
+               if (ret)
+                       break;
+
+       } while (index++);
+}
+
+#else
+static void of_gpiochip_add_pin_range(struct gpio_chip *chip) {}
+#endif
+
 void of_gpiochip_add(struct gpio_chip *chip)
 {
        if ((!chip->of_node) && (chip->dev))
@@ -229,11 +278,14 @@ void of_gpiochip_add(struct gpio_chip *chip)
                chip->of_xlate = of_gpio_simple_xlate;
        }
 
+       of_gpiochip_add_pin_range(chip);
        of_node_get(chip->of_node);
 }
 
 void of_gpiochip_remove(struct gpio_chip *chip)
 {
+       gpiochip_remove_pin_ranges(chip);
+
        if (chip->of_node)
                of_node_put(chip->of_node);
 }
index fd2b71c..199fca1 100644 (file)
@@ -651,9 +651,11 @@ static ssize_t export_store(struct class *class,
         */
 
        status = gpio_request(gpio, "sysfs");
-       if (status < 0)
+       if (status < 0) {
+               if (status == -EPROBE_DEFER)
+                       status = -ENODEV;
                goto done;
-
+       }
        status = gpio_export(gpio, true);
        if (status < 0)
                gpio_free(gpio);
@@ -1118,6 +1120,10 @@ int gpiochip_add(struct gpio_chip *chip)
                }
        }
 
+#ifdef CONFIG_PINCTRL
+       INIT_LIST_HEAD(&chip->pin_ranges);
+#endif
+
        of_gpiochip_add(chip);
 
 unlock:
@@ -1158,6 +1164,7 @@ int gpiochip_remove(struct gpio_chip *chip)
 
        spin_lock_irqsave(&gpio_lock, flags);
 
+       gpiochip_remove_pin_ranges(chip);
        of_gpiochip_remove(chip);
 
        for (id = chip->base; id < chip->base + chip->ngpio; id++) {
@@ -1215,6 +1222,77 @@ struct gpio_chip *gpiochip_find(void *data,
 }
 EXPORT_SYMBOL_GPL(gpiochip_find);
 
+#ifdef CONFIG_PINCTRL
+
+/**
+ * gpiochip_add_pin_range() - add a range for GPIO <-> pin mapping
+ * @chip: the gpiochip to add the range for
+ * @pinctrl_name: the dev_name() of the pin controller to map to
+ * @gpio_offset: the start offset in the current gpio_chip number space
+ * @pin_offset: the start offset in the pin controller number space
+ * @npins: the number of pins from the offset of each pin space (GPIO and
+ *     pin controller) to accumulate in this range
+ */
+int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
+                          unsigned int gpio_offset, unsigned int pin_offset,
+                          unsigned int npins)
+{
+       struct gpio_pin_range *pin_range;
+       int ret;
+
+       pin_range = kzalloc(sizeof(*pin_range), GFP_KERNEL);
+       if (!pin_range) {
+               pr_err("%s: GPIO chip: failed to allocate pin ranges\n",
+                               chip->label);
+               return -ENOMEM;
+       }
+
+       /* Use local offset as range ID */
+       pin_range->range.id = gpio_offset;
+       pin_range->range.gc = chip;
+       pin_range->range.name = chip->label;
+       pin_range->range.base = chip->base + gpio_offset;
+       pin_range->range.pin_base = pin_offset;
+       pin_range->range.npins = npins;
+       pin_range->pctldev = pinctrl_find_and_add_gpio_range(pinctl_name,
+                       &pin_range->range);
+       if (IS_ERR(pin_range->pctldev)) {
+               ret = PTR_ERR(pin_range->pctldev);
+               pr_err("%s: GPIO chip: could not create pin range\n",
+                      chip->label);
+               kfree(pin_range);
+               return ret;
+       }
+       pr_debug("GPIO chip %s: created GPIO range %d->%d ==> %s PIN %d->%d\n",
+                chip->label, gpio_offset, gpio_offset + npins - 1,
+                pinctl_name,
+                pin_offset, pin_offset + npins - 1);
+
+       list_add_tail(&pin_range->node, &chip->pin_ranges);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(gpiochip_add_pin_range);
+
+/**
+ * gpiochip_remove_pin_ranges() - remove all the GPIO <-> pin mappings
+ * @chip: the chip to remove all the mappings for
+ */
+void gpiochip_remove_pin_ranges(struct gpio_chip *chip)
+{
+       struct gpio_pin_range *pin_range, *tmp;
+
+       list_for_each_entry_safe(pin_range, tmp, &chip->pin_ranges, node) {
+               list_del(&pin_range->node);
+               pinctrl_remove_gpio_range(pin_range->pctldev,
+                               &pin_range->range);
+               kfree(pin_range);
+       }
+}
+EXPORT_SYMBOL_GPL(gpiochip_remove_pin_ranges);
+
+#endif /* CONFIG_PINCTRL */
+
 /* These "optional" allocation calls help prevent drivers from stomping
  * on each other, and help provide better diagnostics in debugfs.
  * They're called even less than the "set direction" calls.
@@ -1228,8 +1306,10 @@ int gpio_request(unsigned gpio, const char *label)
 
        spin_lock_irqsave(&gpio_lock, flags);
 
-       if (!gpio_is_valid(gpio))
+       if (!gpio_is_valid(gpio)) {
+               status = -EINVAL;
                goto done;
+       }
        desc = &gpio_desc[gpio];
        chip = desc->chip;
        if (chip == NULL)
index 09e11a5..fd9d0af 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 7ef1b67..133b413 100644 (file)
@@ -121,6 +121,8 @@ int drm_open(struct inode *inode, struct file *filp)
        int minor_id = iminor(inode);
        struct drm_minor *minor;
        int retcode = 0;
+       int need_setup = 0;
+       struct address_space *old_mapping;
 
        minor = idr_find(&drm_minors_idr, minor_id);
        if (!minor)
@@ -132,23 +134,37 @@ int drm_open(struct inode *inode, struct file *filp)
        if (drm_device_is_unplugged(dev))
                return -ENODEV;
 
+       if (!dev->open_count++)
+               need_setup = 1;
+       mutex_lock(&dev->struct_mutex);
+       old_mapping = dev->dev_mapping;
+       if (old_mapping == NULL)
+               dev->dev_mapping = &inode->i_data;
+       /* ihold ensures nobody can remove inode with our i_data */
+       ihold(container_of(dev->dev_mapping, struct inode, i_data));
+       inode->i_mapping = dev->dev_mapping;
+       filp->f_mapping = dev->dev_mapping;
+       mutex_unlock(&dev->struct_mutex);
+
        retcode = drm_open_helper(inode, filp, dev);
-       if (!retcode) {
-               atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
-               if (!dev->open_count++)
-                       retcode = drm_setup(dev);
-       }
-       if (!retcode) {
-               mutex_lock(&dev->struct_mutex);
-               if (dev->dev_mapping == NULL)
-                       dev->dev_mapping = &inode->i_data;
-               /* ihold ensures nobody can remove inode with our i_data */
-               ihold(container_of(dev->dev_mapping, struct inode, i_data));
-               inode->i_mapping = dev->dev_mapping;
-               filp->f_mapping = dev->dev_mapping;
-               mutex_unlock(&dev->struct_mutex);
+       if (retcode)
+               goto err_undo;
+       atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
+       if (need_setup) {
+               retcode = drm_setup(dev);
+               if (retcode)
+                       goto err_undo;
        }
+       return 0;
 
+err_undo:
+       mutex_lock(&dev->struct_mutex);
+       filp->f_mapping = old_mapping;
+       inode->i_mapping = old_mapping;
+       iput(container_of(dev->dev_mapping, struct inode, i_data));
+       dev->dev_mapping = old_mapping;
+       mutex_unlock(&dev->struct_mutex);
+       dev->open_count--;
        return retcode;
 }
 EXPORT_SYMBOL(drm_open);
index cdf8b1e..d4b20ce 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),
@@ -239,7 +237,7 @@ int drm_vma_info(struct seq_file *m, void *data)
        mutex_lock(&dev->struct_mutex);
        seq_printf(m, "vma use count: %d, high_memory = %pK, 0x%pK\n",
                   atomic_read(&dev->vma_count),
-                  high_memory, (void *)virt_to_phys(high_memory));
+                  high_memory, (void *)(unsigned long)virt_to_phys(high_memory));
 
        list_for_each_entry(pt, &dev->vmalist, head) {
                vma = pt->vma;
index aaeb6f8..b8a282e 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 59a26e5..fc345d4 100644 (file)
@@ -1,6 +1,6 @@
 config DRM_EXYNOS
        tristate "DRM Support for Samsung SoC EXYNOS Series"
-       depends on DRM && PLAT_SAMSUNG
+       depends on DRM && (PLAT_SAMSUNG || ARCH_MULTIPLATFORM)
        select DRM_KMS_HELPER
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
index 18c2718..0f68a28 100644 (file)
@@ -374,6 +374,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
        exynos_connector->encoder_id = encoder->base.id;
        exynos_connector->manager = manager;
        exynos_connector->dpms = DRM_MODE_DPMS_OFF;
+       connector->dpms = DRM_MODE_DPMS_OFF;
        connector->encoder = encoder;
 
        err = drm_mode_connector_attach_encoder(connector, encoder);
index e51503f..f2df06c 100644 (file)
  * @manager: specific encoder has its own manager to control a hardware
  *     appropriately and we can access a hardware drawing on this manager.
  * @dpms: store the encoder dpms value.
+ * @updated: indicate whether overlay data updating is needed or not.
  */
 struct exynos_drm_encoder {
        struct drm_crtc                 *old_crtc;
        struct drm_encoder              drm_encoder;
        struct exynos_drm_manager       *manager;
-       int dpms;
+       int                             dpms;
+       bool                            updated;
 };
 
 static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode)
@@ -85,7 +87,9 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
        switch (mode) {
        case DRM_MODE_DPMS_ON:
                if (manager_ops && manager_ops->apply)
-                       manager_ops->apply(manager->dev);
+                       if (!exynos_encoder->updated)
+                               manager_ops->apply(manager->dev);
+
                exynos_drm_connector_power(encoder, mode);
                exynos_encoder->dpms = mode;
                break;
@@ -94,6 +98,7 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
        case DRM_MODE_DPMS_OFF:
                exynos_drm_connector_power(encoder, mode);
                exynos_encoder->dpms = mode;
+               exynos_encoder->updated = false;
                break;
        default:
                DRM_ERROR("unspecified mode %d\n", mode);
@@ -205,13 +210,28 @@ static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
 
 static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
 {
-       struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
+       struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
+       struct exynos_drm_manager *manager = exynos_encoder->manager;
        struct exynos_drm_manager_ops *manager_ops = manager->ops;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
        if (manager_ops && manager_ops->commit)
                manager_ops->commit(manager->dev);
+
+       /*
+        * this will avoid one issue that overlay data is updated to
+        * real hardware two times.
+        * And this variable will be used to check if the data was
+        * already updated or not by exynos_drm_encoder_dpms function.
+        */
+       exynos_encoder->updated = true;
+
+       /*
+        * In case of setcrtc, there is no way to update encoder's dpms
+        * so update it here.
+        */
+       exynos_encoder->dpms = DRM_MODE_DPMS_ON;
 }
 
 static void exynos_drm_encoder_disable(struct drm_encoder *encoder)
@@ -401,19 +421,6 @@ void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
                manager_ops->dpms(manager->dev, mode);
 
        /*
-        * set current mode to new one so that data aren't updated into
-        * registers by drm_helper_connector_dpms two times.
-        *
-        * in case that drm_crtc_helper_set_mode() is called,
-        * overlay_ops->commit() and manager_ops->commit() callbacks
-        * can be called two times, first at drm_crtc_helper_set_mode()
-        * and second at drm_helper_connector_dpms().
-        * so with this setting, when drm_helper_connector_dpms() is called
-        * encoder->funcs->dpms() will be ignored.
-        */
-       exynos_encoder->dpms = mode;
-
-       /*
         * if this condition is ok then it means that the crtc is already
         * detached from encoder and last function for detaching is properly
         * done, so clear pipe from manager to prevent repeated call.
@@ -506,6 +513,6 @@ void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data)
         * because the setting for disabling the overlay will be updated
         * at vsync.
         */
-       if (overlay_ops->wait_for_vblank)
+       if (overlay_ops && overlay_ops->wait_for_vblank)
                overlay_ops->wait_for_vblank(manager->dev);
 }
index 67eb6ba..e7466c4 100644 (file)
@@ -87,7 +87,8 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
 
        dev->mode_config.fb_base = (resource_size_t)buffer->dma_addr;
        fbi->screen_base = buffer->kvaddr + offset;
-       fbi->fix.smem_start = (unsigned long)(buffer->dma_addr + offset);
+       fbi->fix.smem_start = (unsigned long)(page_to_phys(buffer->pages[0]) +
+                               offset);
        fbi->screen_size = size;
        fbi->fix.smem_len = size;
 
index 130a2b5..e08478f 100644 (file)
@@ -61,11 +61,11 @@ struct fimd_driver_data {
        unsigned int timing_base;
 };
 
-struct fimd_driver_data exynos4_fimd_driver_data = {
+static struct fimd_driver_data exynos4_fimd_driver_data = {
        .timing_base = 0x0,
 };
 
-struct fimd_driver_data exynos5_fimd_driver_data = {
+static struct fimd_driver_data exynos5_fimd_driver_data = {
        .timing_base = 0x20000,
 };
 
index 60b877a..862ca1e 100644 (file)
@@ -204,7 +204,6 @@ exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
                return ret;
 
        plane->crtc = crtc;
-       plane->fb = crtc->fb;
 
        exynos_plane_commit(plane);
        exynos_plane_dpms(plane, DRM_MODE_DPMS_ON);
index 614b2e9..e7fbb82 100644 (file)
@@ -1142,7 +1142,7 @@ static int __devinit mixer_probe(struct platform_device *pdev)
                const struct of_device_id *match;
                match = of_match_node(of_match_ptr(mixer_match_types),
                                                          pdev->dev.of_node);
-               drv = match->data;
+               drv = (struct mixer_drv_data *)match->data;
        } else {
                drv = (struct mixer_drv_data *)
                        platform_get_device_id(pdev)->driver_data;
index 38f3a6c..3edd981 100644 (file)
@@ -303,10 +303,10 @@ static bool ch7xxx_get_hw_state(struct intel_dvo_device *dvo)
 
        ch7xxx_readb(dvo, CH7xxx_PM, &val);
 
-       if (val & CH7xxx_PM_FPD)
-               return false;
-       else
+       if (val & (CH7xxx_PM_DVIL | CH7xxx_PM_DVIP))
                return true;
+       else
+               return false;
 }
 
 static void ch7xxx_dump_regs(struct intel_dvo_device *dvo)
index c9bfd83..61ae104 100644 (file)
@@ -1505,7 +1505,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                goto put_gmch;
        }
 
-       i915_kick_out_firmware_fb(dev_priv);
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               i915_kick_out_firmware_fb(dev_priv);
 
        pci_set_master(dev->pdev);
 
index aac4e5e..6770ee6 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 4f2831a..f511fa2 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);
@@ -1341,9 +1342,14 @@ int __must_check i915_gem_object_get_pages(struct drm_i915_gem_object *obj);
 static inline struct page *i915_gem_object_get_page(struct drm_i915_gem_object *obj, int n)
 {
        struct scatterlist *sg = obj->pages->sgl;
-       while (n >= SG_MAX_SINGLE_ALLOC) {
+       int nents = obj->pages->nents;
+       while (nents > SG_MAX_SINGLE_ALLOC) {
+               if (n < SG_MAX_SINGLE_ALLOC - 1)
+                       break;
+
                sg = sg_chain_ptr(sg + SG_MAX_SINGLE_ALLOC - 1);
                n -= SG_MAX_SINGLE_ALLOC - 1;
+               nents -= SG_MAX_SINGLE_ALLOC - 1;
        }
        return sg_page(sg+n);
 }
@@ -1427,7 +1433,7 @@ int __must_check i915_gpu_idle(struct drm_device *dev);
 int __must_check i915_gem_idle(struct drm_device *dev);
 int i915_add_request(struct intel_ring_buffer *ring,
                     struct drm_file *file,
-                    struct drm_i915_gem_request *request);
+                    u32 *seqno);
 int __must_check i915_wait_seqno(struct intel_ring_buffer *ring,
                                 uint32_t seqno);
 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
index 19dbdd7..9b285da 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;
        }
 }
@@ -1794,7 +1796,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
         */
        mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping;
        gfp = mapping_gfp_mask(mapping);
-       gfp |= __GFP_NORETRY | __GFP_NOWARN;
+       gfp |= __GFP_NORETRY | __GFP_NOWARN | __GFP_NO_KSWAPD;
        gfp &= ~(__GFP_IO | __GFP_WAIT);
        for_each_sg(st->sgl, sg, page_count, i) {
                page = shmem_read_mapping_page_gfp(mapping, i, gfp);
@@ -1807,7 +1809,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
                         * our own buffer, now let the real VM do its job and
                         * go down in flames if truly OOM.
                         */
-                       gfp &= ~(__GFP_NORETRY | __GFP_NOWARN);
+                       gfp &= ~(__GFP_NORETRY | __GFP_NOWARN | __GFP_NO_KSWAPD);
                        gfp |= __GFP_IO | __GFP_WAIT;
 
                        i915_gem_shrink_all(dev_priv);
@@ -1815,17 +1817,18 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
                        if (IS_ERR(page))
                                goto err_pages;
 
-                       gfp |= __GFP_NORETRY | __GFP_NOWARN;
+                       gfp |= __GFP_NORETRY | __GFP_NOWARN | __GFP_NO_KSWAPD;
                        gfp &= ~(__GFP_IO | __GFP_WAIT);
                }
 
                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:
@@ -1955,11 +1958,12 @@ i915_gem_next_request_seqno(struct intel_ring_buffer *ring)
 int
 i915_add_request(struct intel_ring_buffer *ring,
                 struct drm_file *file,
-                struct drm_i915_gem_request *request)
+                u32 *out_seqno)
 {
        drm_i915_private_t *dev_priv = ring->dev->dev_private;
-       uint32_t seqno;
+       struct drm_i915_gem_request *request;
        u32 request_ring_position;
+       u32 seqno;
        int was_empty;
        int ret;
 
@@ -1974,11 +1978,9 @@ i915_add_request(struct intel_ring_buffer *ring,
        if (ret)
                return ret;
 
-       if (request == NULL) {
-               request = kmalloc(sizeof(*request), GFP_KERNEL);
-               if (request == NULL)
-                       return -ENOMEM;
-       }
+       request = kmalloc(sizeof(*request), GFP_KERNEL);
+       if (request == NULL)
+               return -ENOMEM;
 
        seqno = i915_gem_next_request_seqno(ring);
 
@@ -2030,6 +2032,8 @@ i915_add_request(struct intel_ring_buffer *ring,
                }
        }
 
+       if (out_seqno)
+               *out_seqno = seqno;
        return 0;
 }
 
@@ -3959,6 +3963,9 @@ i915_gem_init_hw(struct drm_device *dev)
        if (!intel_enable_gtt())
                return -EIO;
 
+       if (IS_HASWELL(dev) && (I915_READ(0x120010) == 1))
+               I915_WRITE(0x9008, I915_READ(0x9008) | 0xf0000);
+
        i915_gem_l3_remap(dev);
 
        i915_gem_init_swizzling(dev);
@@ -4098,7 +4105,6 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
        }
 
        BUG_ON(!list_empty(&dev_priv->mm.active_list));
-       BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
        mutex_unlock(&dev->struct_mutex);
 
        ret = drm_irq_install(dev);
index 64c1be0..a4162dd 100644 (file)
  */
 # define _3D_CHICKEN2_WM_READ_PIPELINED                        (1 << 14)
 #define _3D_CHICKEN3   0x02090
-#define  _3D_CHICKEN_SF_DISABLE_FASTCLIP_CULL          (1 << 5)
+#define  _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL         (1 << 5)
 
 #define MI_MODE                0x0209c
 # define VS_TIMER_DISPATCH                             (1 << 6)
index 0ed6baf..56846ed 100644 (file)
@@ -499,12 +499,8 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
 
        edp = find_section(bdb, BDB_EDP);
        if (!edp) {
-               if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp.support) {
-                       DRM_DEBUG_KMS("No eDP BDB found but eDP panel "
-                                     "supported, assume %dbpp panel color "
-                                     "depth.\n",
-                                     dev_priv->edp.bpp);
-               }
+               if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp.support)
+                       DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported.\n");
                return;
        }
 
@@ -657,9 +653,6 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
        dev_priv->lvds_use_ssc = 1;
        dev_priv->lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1);
        DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq);
-
-       /* eDP data */
-       dev_priv->edp.bpp = 18;
 }
 
 static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
index 893f301..6345878 100644 (file)
@@ -143,7 +143,7 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode)
        int old_dpms;
 
        /* PCH platforms and VLV only support on/off. */
-       if (INTEL_INFO(dev)->gen < 5 && mode != DRM_MODE_DPMS_ON)
+       if (INTEL_INFO(dev)->gen >= 5 && mode != DRM_MODE_DPMS_ON)
                mode = DRM_MODE_DPMS_OFF;
 
        if (mode == connector->dpms)
@@ -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)
@@ -742,7 +729,7 @@ void intel_crt_init(struct drm_device *dev)
 
        crt->base.type = INTEL_OUTPUT_ANALOG;
        crt->base.cloneable = true;
-       if (IS_HASWELL(dev))
+       if (IS_HASWELL(dev) || IS_I830(dev))
                crt->base.crtc_mask = (1 << 0);
        else
                crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
index 2b6ce9b..b426d44 100644 (file)
@@ -3253,6 +3253,16 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 
        if (HAS_PCH_CPT(dev))
                intel_cpt_verify_modeset(dev, intel_crtc->pipe);
+
+       /*
+        * There seems to be a race in PCH platform hw (at least on some
+        * outputs) where an enabled pipe still completes any pageflip right
+        * away (as if the pipe is off) instead of waiting for vblank. As soon
+        * as the first vblank happend, everything works as expected. Hence just
+        * wait for one vblank before returning to avoid strange things
+        * happening.
+        */
+       intel_wait_for_vblank(dev, intel_crtc->pipe);
 }
 
 static void ironlake_crtc_disable(struct drm_crtc *crtc)
@@ -3831,6 +3841,17 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
                        }
                }
 
+               if (intel_encoder->type == INTEL_OUTPUT_EDP) {
+                       /* Use VBT settings if we have an eDP panel */
+                       unsigned int edp_bpc = dev_priv->edp.bpp / 3;
+
+                       if (edp_bpc && edp_bpc < display_bpc) {
+                               DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
+                               display_bpc = edp_bpc;
+                       }
+                       continue;
+               }
+
                /*
                 * HDMI is either 12 or 8, so if the display lets 10bpc sneak
                 * through, clamp it down.  (Note: >12bpc will be caught below.)
@@ -7882,6 +7903,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 },
@@ -7892,8 +7941,7 @@ static struct intel_quirk intel_quirks[] = {
        /* ThinkPad T60 needs pipe A force quirk (bug #16494) */
        { 0x2782, 0x17aa, 0x201a, quirk_pipea_force },
 
-       /* 855 & before need to leave pipe A & dpll A up */
-       { 0x3582, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
+       /* 830/845 need to leave pipe A & dpll A up */
        { 0x2562, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
        { 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
 
@@ -7922,6 +7970,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 */
@@ -8049,29 +8101,42 @@ static void intel_enable_pipe_a(struct drm_device *dev)
 
 }
 
+static bool
+intel_check_plane_mapping(struct intel_crtc *crtc)
+{
+       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+       u32 reg, val;
+
+       if (dev_priv->num_pipe == 1)
+               return true;
+
+       reg = DSPCNTR(!crtc->plane);
+       val = I915_READ(reg);
+
+       if ((val & DISPLAY_PLANE_ENABLE) &&
+           (!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe))
+               return false;
+
+       return true;
+}
+
 static void intel_sanitize_crtc(struct intel_crtc *crtc)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 reg, val;
+       u32 reg;
 
        /* Clear any frame start delays used for debugging left by the BIOS */
        reg = PIPECONF(crtc->pipe);
        I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
 
        /* We need to sanitize the plane -> pipe mapping first because this will
-        * disable the crtc (and hence change the state) if it is wrong. */
-       if (!HAS_PCH_SPLIT(dev)) {
+        * disable the crtc (and hence change the state) if it is wrong. Note
+        * that gen4+ has a fixed plane -> pipe mapping.  */
+       if (INTEL_INFO(dev)->gen < 4 && !intel_check_plane_mapping(crtc)) {
                struct intel_connector *connector;
                bool plane;
 
-               reg = DSPCNTR(crtc->plane);
-               val = I915_READ(reg);
-
-               if ((val & DISPLAY_PLANE_ENABLE) == 0 &&
-                   (!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe))
-                       goto ok;
-
                DRM_DEBUG_KMS("[CRTC:%d] wrong plane connection detected!\n",
                              crtc->base.base.id);
 
@@ -8095,7 +8160,6 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
                WARN_ON(crtc->active);
                crtc->base.enabled = false;
        }
-ok:
 
        if (dev_priv->quirks & QUIRK_PIPEA_FORCE &&
            crtc->pipe == PIPE_A && !crtc->active) {
index d1e8ddb..368ed8e 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);
@@ -2369,8 +2374,9 @@ static void
 intel_dp_destroy(struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
+       struct intel_dp *intel_dp = intel_attached_dp(connector);
 
-       if (intel_dpd_is_edp(dev))
+       if (is_edp(intel_dp))
                intel_panel_destroy_backlight(dev);
 
        drm_sysfs_connector_remove(connector);
index e3166df..edba93b 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 ebff850..d7bc817 100644 (file)
@@ -209,7 +209,6 @@ static void intel_overlay_unmap_regs(struct intel_overlay *overlay,
 }
 
 static int intel_overlay_do_wait_request(struct intel_overlay *overlay,
-                                        struct drm_i915_gem_request *request,
                                         void (*tail)(struct intel_overlay *))
 {
        struct drm_device *dev = overlay->dev;
@@ -218,12 +217,10 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay,
        int ret;
 
        BUG_ON(overlay->last_flip_req);
-       ret = i915_add_request(ring, NULL, request);
-       if (ret) {
-           kfree(request);
-           return ret;
-       }
-       overlay->last_flip_req = request->seqno;
+       ret = i915_add_request(ring, NULL, &overlay->last_flip_req);
+       if (ret)
+               return ret;
+
        overlay->flip_tail = tail;
        ret = i915_wait_seqno(ring, overlay->last_flip_req);
        if (ret)
@@ -240,7 +237,6 @@ static int intel_overlay_on(struct intel_overlay *overlay)
        struct drm_device *dev = overlay->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
-       struct drm_i915_gem_request *request;
        int ret;
 
        BUG_ON(overlay->active);
@@ -248,17 +244,9 @@ static int intel_overlay_on(struct intel_overlay *overlay)
 
        WARN_ON(IS_I830(dev) && !(dev_priv->quirks & QUIRK_PIPEA_FORCE));
 
-       request = kzalloc(sizeof(*request), GFP_KERNEL);
-       if (request == NULL) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
        ret = intel_ring_begin(ring, 4);
-       if (ret) {
-               kfree(request);
-               goto out;
-       }
+       if (ret)
+               return ret;
 
        intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_ON);
        intel_ring_emit(ring, overlay->flip_addr | OFC_UPDATE);
@@ -266,9 +254,7 @@ static int intel_overlay_on(struct intel_overlay *overlay)
        intel_ring_emit(ring, MI_NOOP);
        intel_ring_advance(ring);
 
-       ret = intel_overlay_do_wait_request(overlay, request, NULL);
-out:
-       return ret;
+       return intel_overlay_do_wait_request(overlay, NULL);
 }
 
 /* overlay needs to be enabled in OCMD reg */
@@ -278,17 +264,12 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
        struct drm_device *dev = overlay->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
-       struct drm_i915_gem_request *request;
        u32 flip_addr = overlay->flip_addr;
        u32 tmp;
        int ret;
 
        BUG_ON(!overlay->active);
 
-       request = kzalloc(sizeof(*request), GFP_KERNEL);
-       if (request == NULL)
-               return -ENOMEM;
-
        if (load_polyphase_filter)
                flip_addr |= OFC_UPDATE;
 
@@ -298,22 +279,14 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
                DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
 
        ret = intel_ring_begin(ring, 2);
-       if (ret) {
-               kfree(request);
+       if (ret)
                return ret;
-       }
+
        intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
        intel_ring_emit(ring, flip_addr);
        intel_ring_advance(ring);
 
-       ret = i915_add_request(ring, NULL, request);
-       if (ret) {
-               kfree(request);
-               return ret;
-       }
-
-       overlay->last_flip_req = request->seqno;
-       return 0;
+       return i915_add_request(ring, NULL, &overlay->last_flip_req);
 }
 
 static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
@@ -349,15 +322,10 @@ static int intel_overlay_off(struct intel_overlay *overlay)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
        u32 flip_addr = overlay->flip_addr;
-       struct drm_i915_gem_request *request;
        int ret;
 
        BUG_ON(!overlay->active);
 
-       request = kzalloc(sizeof(*request), GFP_KERNEL);
-       if (request == NULL)
-               return -ENOMEM;
-
        /* According to intel docs the overlay hw may hang (when switching
         * off) without loading the filter coeffs. It is however unclear whether
         * this applies to the disabling of the overlay or to the switching off
@@ -365,22 +333,28 @@ static int intel_overlay_off(struct intel_overlay *overlay)
        flip_addr |= OFC_UPDATE;
 
        ret = intel_ring_begin(ring, 6);
-       if (ret) {
-               kfree(request);
+       if (ret)
                return ret;
-       }
+
        /* wait for overlay to go idle */
        intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
        intel_ring_emit(ring, flip_addr);
        intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
        /* turn overlay off */
-       intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
-       intel_ring_emit(ring, flip_addr);
-       intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+       if (IS_I830(dev)) {
+               /* Workaround: Don't disable the overlay fully, since otherwise
+                * it dies on the next OVERLAY_ON cmd. */
+               intel_ring_emit(ring, MI_NOOP);
+               intel_ring_emit(ring, MI_NOOP);
+               intel_ring_emit(ring, MI_NOOP);
+       } else {
+               intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
+               intel_ring_emit(ring, flip_addr);
+               intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+       }
        intel_ring_advance(ring);
 
-       return intel_overlay_do_wait_request(overlay, request,
-                                            intel_overlay_off_tail);
+       return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail);
 }
 
 /* recover from an interruption due to a signal
@@ -425,24 +399,16 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
                return 0;
 
        if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) {
-               struct drm_i915_gem_request *request;
-
                /* synchronous slowpath */
-               request = kzalloc(sizeof(*request), GFP_KERNEL);
-               if (request == NULL)
-                       return -ENOMEM;
-
                ret = intel_ring_begin(ring, 2);
-               if (ret) {
-                       kfree(request);
+               if (ret)
                        return ret;
-               }
 
                intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
                intel_ring_emit(ring, MI_NOOP);
                intel_ring_advance(ring);
 
-               ret = intel_overlay_do_wait_request(overlay, request,
+               ret = intel_overlay_do_wait_request(overlay,
                                                    intel_overlay_release_old_vid_tail);
                if (ret)
                        return ret;
index e019b23..e2aacd3 100644 (file)
@@ -435,7 +435,7 @@ int intel_panel_setup_backlight(struct drm_device *dev)
        props.type = BACKLIGHT_RAW;
        props.max_brightness = _intel_panel_get_max_backlight(dev);
        if (props.max_brightness == 0) {
-               DRM_ERROR("Failed to get maximum backlight value\n");
+               DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n");
                return -ENODEV;
        }
        dev_priv->backlight =
index b3b4b6c..442968f 100644 (file)
@@ -2373,15 +2373,9 @@ int intel_enable_rc6(const struct drm_device *dev)
        if (i915_enable_rc6 >= 0)
                return i915_enable_rc6;
 
-       if (INTEL_INFO(dev)->gen == 5) {
-#ifdef CONFIG_INTEL_IOMMU
-               /* Disable rc6 on ilk if VT-d is on. */
-               if (intel_iommu_gfx_mapped)
-                       return false;
-#endif
-               DRM_DEBUG_DRIVER("Ironlake: only RC6 available\n");
-               return INTEL_RC6_ENABLE;
-       }
+       /* Disable RC6 on Ironlake */
+       if (INTEL_INFO(dev)->gen == 5)
+               return 0;
 
        if (IS_HASWELL(dev)) {
                DRM_DEBUG_DRIVER("Haswell: only RC6 available\n");
@@ -3442,8 +3436,8 @@ static void gen6_init_clock_gating(struct drm_device *dev)
                   GEN6_RCCUNIT_CLOCK_GATE_DISABLE);
 
        /* Bspec says we need to always set all mask bits. */
-       I915_WRITE(_3D_CHICKEN, (0xFFFF << 16) |
-                  _3D_CHICKEN_SF_DISABLE_FASTCLIP_CULL);
+       I915_WRITE(_3D_CHICKEN3, (0xFFFF << 16) |
+                  _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL);
 
        /*
         * According to the spec the following bits should be
index 0007a4d..a6ac0b4 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 {
@@ -889,6 +894,45 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
 }
 #endif
 
+static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo,
+                                      unsigned if_index, uint8_t tx_rate,
+                                      uint8_t *data, unsigned length)
+{
+       uint8_t set_buf_index[2] = { if_index, 0 };
+       uint8_t hbuf_size, tmp[8];
+       int i;
+
+       if (!intel_sdvo_set_value(intel_sdvo,
+                                 SDVO_CMD_SET_HBUF_INDEX,
+                                 set_buf_index, 2))
+               return false;
+
+       if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HBUF_INFO,
+                                 &hbuf_size, 1))
+               return false;
+
+       /* Buffer size is 0 based, hooray! */
+       hbuf_size++;
+
+       DRM_DEBUG_KMS("writing sdvo hbuf: %i, hbuf_size %i, hbuf_size: %i\n",
+                     if_index, length, hbuf_size);
+
+       for (i = 0; i < hbuf_size; i += 8) {
+               memset(tmp, 0, 8);
+               if (i < length)
+                       memcpy(tmp, data + i, min_t(unsigned, 8, length - i));
+
+               if (!intel_sdvo_set_value(intel_sdvo,
+                                         SDVO_CMD_SET_HBUF_DATA,
+                                         tmp, 8))
+                       return false;
+       }
+
+       return intel_sdvo_set_value(intel_sdvo,
+                                   SDVO_CMD_SET_HBUF_TXRATE,
+                                   &tx_rate, 1);
+}
+
 static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
 {
        struct dip_infoframe avi_if = {
@@ -896,11 +940,7 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
                .ver = DIP_VERSION_AVI,
                .len = DIP_LEN_AVI,
        };
-       uint8_t tx_rate = SDVO_HBUF_TX_VSYNC;
-       uint8_t set_buf_index[2] = { 1, 0 };
        uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)];
-       uint64_t *data = (uint64_t *)sdvo_data;
-       unsigned i;
 
        intel_dip_infoframe_csum(&avi_if);
 
@@ -910,22 +950,9 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
        sdvo_data[3] = avi_if.checksum;
        memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi));
 
-       if (!intel_sdvo_set_value(intel_sdvo,
-                                 SDVO_CMD_SET_HBUF_INDEX,
-                                 set_buf_index, 2))
-               return false;
-
-       for (i = 0; i < sizeof(sdvo_data); i += 8) {
-               if (!intel_sdvo_set_value(intel_sdvo,
-                                         SDVO_CMD_SET_HBUF_DATA,
-                                         data, 8))
-                       return false;
-               data++;
-       }
-
-       return intel_sdvo_set_value(intel_sdvo,
-                                   SDVO_CMD_SET_HBUF_TXRATE,
-                                   &tx_rate, 1);
+       return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF,
+                                         SDVO_HBUF_TX_VSYNC,
+                                         sdvo_data, sizeof(sdvo_data));
 }
 
 static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo)
@@ -984,6 +1011,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 +1120,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));
@@ -2171,7 +2201,6 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
                connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
                intel_sdvo->is_hdmi = true;
        }
-       intel_sdvo->base.cloneable = true;
 
        intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
        if (intel_sdvo->is_hdmi)
@@ -2202,7 +2231,6 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type)
 
        intel_sdvo->is_tv = true;
        intel_sdvo->base.needs_tv_clock = true;
-       intel_sdvo->base.cloneable = false;
 
        intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
 
@@ -2245,8 +2273,6 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device)
                intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1;
        }
 
-       intel_sdvo->base.cloneable = true;
-
        intel_sdvo_connector_init(intel_sdvo_connector,
                                  intel_sdvo);
        return true;
@@ -2277,11 +2303,6 @@ 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;
-
        intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
        if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))
                goto err;
@@ -2354,6 +2375,18 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags)
        return true;
 }
 
+static void intel_sdvo_output_cleanup(struct intel_sdvo *intel_sdvo)
+{
+       struct drm_device *dev = intel_sdvo->base.base.dev;
+       struct drm_connector *connector, *tmp;
+
+       list_for_each_entry_safe(connector, tmp,
+                                &dev->mode_config.connector_list, head) {
+               if (intel_attached_encoder(connector) == &intel_sdvo->base)
+                       intel_sdvo_destroy(connector);
+       }
+}
+
 static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo,
                                          struct intel_sdvo_connector *intel_sdvo_connector,
                                          int type)
@@ -2677,9 +2710,20 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
                                    intel_sdvo->caps.output_flags) != true) {
                DRM_DEBUG_KMS("SDVO output failed to setup on %s\n",
                              SDVO_NAME(intel_sdvo));
-               goto err;
+               /* Output_setup can leave behind connectors! */
+               goto err_output;
        }
 
+       /*
+        * Cloning SDVO with anything is often impossible, since the SDVO
+        * encoder can request a special input timing mode. And even if that's
+        * not the case we have evidence that cloning a plain unscaled mode with
+        * VGA doesn't really work. Furthermore the cloning flags are way too
+        * simplistic anyway to express such constraints, so just give up on
+        * cloning for SDVO encoders.
+        */
+       intel_sdvo->base.cloneable = false;
+
        /* Only enable the hotplug irq if we need it, to work around noisy
         * hotplug lines.
         */
@@ -2690,12 +2734,12 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
 
        /* Set the input timing to the screen. Assume always input 0. */
        if (!intel_sdvo_set_target_input(intel_sdvo))
-               goto err;
+               goto err_output;
 
        if (!intel_sdvo_get_input_pixel_clock_range(intel_sdvo,
                                                    &intel_sdvo->pixel_clock_min,
                                                    &intel_sdvo->pixel_clock_max))
-               goto err;
+               goto err_output;
 
        DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, "
                        "clock range %dMHz - %dMHz, "
@@ -2715,6 +2759,9 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
                        (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N');
        return true;
 
+err_output:
+       intel_sdvo_output_cleanup(intel_sdvo);
+
 err:
        drm_encoder_cleanup(&intel_encoder->base);
        i2c_del_adapter(&intel_sdvo->ddc);
index 9d03014..770bdd6 100644 (file)
@@ -708,6 +708,8 @@ struct intel_sdvo_enhancements_arg {
 #define SDVO_CMD_SET_AUDIO_STAT                0x91
 #define SDVO_CMD_GET_AUDIO_STAT                0x92
 #define SDVO_CMD_SET_HBUF_INDEX                0x93
+  #define SDVO_HBUF_INDEX_ELD          0
+  #define SDVO_HBUF_INDEX_AVI_IF       1
 #define SDVO_CMD_GET_HBUF_INDEX                0x94
 #define SDVO_CMD_GET_HBUF_INFO         0x95
 #define SDVO_CMD_SET_HBUF_AV_SPLIT     0x96
index 1f34549..70586fd 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 bfddf87..a6d3cd6 100644 (file)
@@ -218,13 +218,16 @@ nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block)
        node = kzalloc(sizeof(*node), GFP_KERNEL);
        if (!node)
                return -ENOMEM;
-       node->offset = roundup(offset, mm->block_size);
-       node->length = rounddown(offset + length, mm->block_size) - node->offset;
+
+       if (length) {
+               node->offset  = roundup(offset, mm->block_size);
+               node->length  = rounddown(offset + length, mm->block_size);
+               node->length -= node->offset;
+       }
 
        list_add_tail(&node->nl_entry, &mm->nodes);
        list_add_tail(&node->fl_entry, &mm->free);
        mm->heap_nodes++;
-       mm->heap_size += length;
        return 0;
 }
 
@@ -236,7 +239,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 16a9afb..15b182c 100644 (file)
@@ -22,6 +22,8 @@
  * Authors: Ben Skeggs
  */
 
+#include <subdev/bar.h>
+
 #include <engine/software.h>
 #include <engine/disp.h>
 
@@ -37,6 +39,7 @@ nv50_disp_sclass[] = {
 static void
 nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc)
 {
+       struct nouveau_bar *bar = nouveau_bar(priv);
        struct nouveau_disp *disp = &priv->base;
        struct nouveau_software_chan *chan, *temp;
        unsigned long flags;
@@ -46,19 +49,25 @@ nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc)
                if (chan->vblank.crtc != crtc)
                        continue;
 
-               nv_wr32(priv, 0x001704, chan->vblank.channel);
-               nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma);
-
-               if (nv_device(priv)->chipset == 0x50) {
-                       nv_wr32(priv, 0x001570, chan->vblank.offset);
-                       nv_wr32(priv, 0x001574, chan->vblank.value);
+               if (nv_device(priv)->chipset >= 0xc0) {
+                       nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel);
+                       bar->flush(bar);
+                       nv_wr32(priv, 0x06000c,
+                               upper_32_bits(chan->vblank.offset));
+                       nv_wr32(priv, 0x060010,
+                               lower_32_bits(chan->vblank.offset));
+                       nv_wr32(priv, 0x060014, chan->vblank.value);
                } else {
-                       if (nv_device(priv)->chipset >= 0xc0) {
-                               nv_wr32(priv, 0x06000c,
-                                       upper_32_bits(chan->vblank.offset));
+                       nv_wr32(priv, 0x001704, chan->vblank.channel);
+                       nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma);
+                       bar->flush(bar);
+                       if (nv_device(priv)->chipset == 0x50) {
+                               nv_wr32(priv, 0x001570, chan->vblank.offset);
+                               nv_wr32(priv, 0x001574, chan->vblank.value);
+                       } else {
+                               nv_wr32(priv, 0x060010, chan->vblank.offset);
+                               nv_wr32(priv, 0x060014, chan->vblank.value);
                        }
-                       nv_wr32(priv, 0x060010, chan->vblank.offset);
-                       nv_wr32(priv, 0x060014, chan->vblank.value);
                }
 
                list_del(&chan->vblank.head);
index e45035e..7bbb1e1 100644 (file)
@@ -669,21 +669,27 @@ nv40_grctx_fill(struct nouveau_device *device, struct nouveau_gpuobj *mem)
                           });
 }
 
-void
+int
 nv40_grctx_init(struct nouveau_device *device, u32 *size)
 {
-       u32 ctxprog[256], i;
+       u32 *ctxprog = kmalloc(256 * 4, GFP_KERNEL), i;
        struct nouveau_grctx ctx = {
                .device = device,
                .mode = NOUVEAU_GRCTX_PROG,
                .data = ctxprog,
-               .ctxprog_max = ARRAY_SIZE(ctxprog)
+               .ctxprog_max = 256,
        };
 
+       if (!ctxprog)
+               return -ENOMEM;
+
        nv40_grctx_generate(&ctx);
 
        nv_wr32(device, 0x400324, 0);
        for (i = 0; i < ctx.ctxprog_len; i++)
                nv_wr32(device, 0x400328, ctxprog[i]);
        *size = ctx.ctxvals_pos * 4;
+
+       kfree(ctxprog);
+       return 0;
 }
index 8d00210..cc6574e 100644 (file)
@@ -156,8 +156,8 @@ nv40_graph_context_ctor(struct nouveau_object *parent,
 static int
 nv40_graph_context_fini(struct nouveau_object *object, bool suspend)
 {
-       struct nv04_graph_priv *priv = (void *)object->engine;
-       struct nv04_graph_chan *chan = (void *)object;
+       struct nv40_graph_priv *priv = (void *)object->engine;
+       struct nv40_graph_chan *chan = (void *)object;
        u32 inst = 0x01000000 | nv_gpuobj(chan)->addr >> 4;
        int ret = 0;
 
@@ -346,7 +346,9 @@ nv40_graph_init(struct nouveau_object *object)
                return ret;
 
        /* generate and upload context program */
-       nv40_grctx_init(nv_device(priv), &priv->size);
+       ret = nv40_grctx_init(nv_device(priv), &priv->size);
+       if (ret)
+               return ret;
 
        /* No context present currently */
        nv_wr32(priv, NV40_PGRAPH_CTXCTL_CUR, 0x00000000);
index d2ac975..7da35a4 100644 (file)
@@ -15,7 +15,7 @@ nv44_graph_class(void *priv)
        return !(0x0baf & (1 << (device->chipset & 0x0f)));
 }
 
-void nv40_grctx_init(struct nouveau_device *, u32 *size);
+int  nv40_grctx_init(struct nouveau_device *, u32 *size);
 void nv40_grctx_fill(struct nouveau_device *, struct nouveau_gpuobj *);
 
 #endif
index 1241857..f7c581a 100644 (file)
@@ -38,7 +38,7 @@ struct nv40_mpeg_priv {
 };
 
 struct nv40_mpeg_chan {
-       struct nouveau_mpeg base;
+       struct nouveau_mpeg_chan base;
 };
 
 /*******************************************************************************
index 9ee9bf4..975137b 100644 (file)
@@ -19,7 +19,6 @@ struct nouveau_mm {
 
        u32 block_size;
        int heap_nodes;
-       u32 heap_size;
 };
 
 int  nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block);
index 818feab..486f1a9 100644 (file)
@@ -175,14 +175,18 @@ nv_mo32(void *obj, u32 addr, u32 mask, u32 data)
        return temp;
 }
 
-static inline bool
-nv_strncmp(void *obj, u32 addr, u32 len, const char *str)
+static inline int
+nv_memcmp(void *obj, u32 addr, const char *str, u32 len)
 {
+       unsigned char c1, c2;
+
        while (len--) {
-               if (nv_ro08(obj, addr++) != *(str++))
-                       return false;
+               c1 = nv_ro08(obj, addr++);
+               c2 = *(str++);
+               if (c1 != c2)
+                       return c1 - c2;
        }
-       return true;
+       return 0;
 }
 
 #endif
index 39e73b9..41b7a6a 100644 (file)
@@ -54,6 +54,7 @@ int nv04_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *,
                        int clk, struct nouveau_pll_vals *);
 int nv04_clock_pll_prog(struct nouveau_clock *, u32 reg1,
                        struct nouveau_pll_vals *);
-
+int nva3_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *,
+                       int clk, struct nouveau_pll_vals *);
 
 #endif
index dcb5c2b..70ca7d5 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 9ed6e72..c511971 100644 (file)
@@ -43,7 +43,7 @@ dcb_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
        *ver = nv_ro08(bios, dcb);
 
        if (*ver >= 0x41) {
-               nv_warn(bios, "DCB *ver 0x%02x unknown\n", *ver);
+               nv_warn(bios, "DCB version 0x%02x unknown\n", *ver);
                return 0x0000;
        } else
        if (*ver >= 0x30) {
@@ -64,7 +64,7 @@ dcb_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
                }
        } else
        if (*ver >= 0x15) {
-               if (!nv_strncmp(bios, dcb - 7, 7, "DEV_REC")) {
+               if (!nv_memcmp(bios, dcb - 7, "DEV_REC", 7)) {
                        u16 i2c = nv_ro16(bios, dcb + 2);
                        *hdr = 4;
                        *cnt = (i2c - dcb) / 10;
index 5e5f4cd..f835501 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 cc8d7d1..9068c98 100644 (file)
@@ -66,6 +66,24 @@ nva3_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq)
        return ret;
 }
 
+int
+nva3_clock_pll_calc(struct nouveau_clock *clock, struct nvbios_pll *info,
+                   int clk, struct nouveau_pll_vals *pv)
+{
+       int ret, N, M, P;
+
+       ret = nva3_pll_calc(clock, info, clk, &N, NULL, &M, &P);
+
+       if (ret > 0) {
+               pv->refclk = info->refclk;
+               pv->N1 = N;
+               pv->M1 = M;
+               pv->log2P = P;
+       }
+       return ret;
+}
+
+
 static int
 nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                struct nouveau_oclass *oclass, void *data, u32 size,
@@ -80,6 +98,7 @@ nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                return ret;
 
        priv->base.pll_set = nva3_clock_pll_set;
+       priv->base.pll_calc = nva3_clock_pll_calc;
        return 0;
 }
 
index 5ccce0b..f6962c9 100644 (file)
@@ -79,6 +79,7 @@ nvc0_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                return ret;
 
        priv->base.pll_set = nvc0_clock_pll_set;
+       priv->base.pll_calc = nva3_clock_pll_calc;
        return 0;
 }
 
index 436e9ef..5f57080 100644 (file)
@@ -219,13 +219,11 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                             ((priv->base.ram.size & 0x000000ff) << 32);
 
        tags = nv_rd32(priv, 0x100320);
-       if (tags) {
-               ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1);
-               if (ret)
-                       return ret;
+       ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1);
+       if (ret)
+               return ret;
 
-               nv_debug(priv, "%d compression tags\n", tags);
-       }
+       nv_debug(priv, "%d compression tags\n", tags);
 
        size = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail;
        switch (device->chipset) {
@@ -237,6 +235,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,
@@ -277,7 +276,6 @@ nv50_fb_dtor(struct nouveau_object *object)
                __free_page(priv->r100c08_page);
        }
 
-       nouveau_mm_fini(&priv->base.vram);
        nouveau_fb_destroy(&priv->base);
 }
 
index 3d2c883..dbfc2ab 100644 (file)
@@ -292,7 +292,7 @@ nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                case DCB_I2C_NVIO_BIT:
                        port->drive = info.drive & 0x0f;
                        if (device->card_type < NV_D0) {
-                               if (info.drive >= ARRAY_SIZE(nv50_i2c_port))
+                               if (port->drive >= ARRAY_SIZE(nv50_i2c_port))
                                        break;
                                port->drive = nv50_i2c_port[port->drive];
                                port->sense = port->drive;
index b292379..5231786 100644 (file)
@@ -134,7 +134,7 @@ nouveau_therm_fan_sense(struct nouveau_therm *therm)
        end = ptimer->read(ptimer);
 
        if (cycles == 5) {
-               tach = (u64)60000000000;
+               tach = (u64)60000000000ULL;
                do_div(tach, (end - start));
                return tach;
        } else
index 0203e1e..9474cfc 100644 (file)
@@ -67,7 +67,7 @@ nv41_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt)
 static void
 nv41_vm_flush(struct nouveau_vm *vm)
 {
-       struct nv04_vm_priv *priv = (void *)vm->vmm;
+       struct nv04_vmmgr_priv *priv = (void *)vm->vmm;
 
        mutex_lock(&nv_subdev(priv)->mutex);
        nv_wr32(priv, 0x100810, 0x00000022);
@@ -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 0ac18d0..aa81314 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 cc79c79..cbf1fc6 100644 (file)
@@ -241,6 +241,10 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
 
        if (unlikely(!abi16))
                return -ENOMEM;
+
+       if (!drm->channel)
+               return nouveau_abi16_put(abi16, -ENODEV);
+
        client = nv_client(abi16->client);
 
        if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0)
index 259e5f1..35ac57f 100644 (file)
@@ -456,6 +456,7 @@ static struct ttm_tt *
 nouveau_ttm_tt_create(struct ttm_bo_device *bdev, unsigned long size,
                      uint32_t page_flags, struct page *dummy_read)
 {
+#if __OS_HAS_AGP
        struct nouveau_drm *drm = nouveau_bdev(bdev);
        struct drm_device *dev = drm->dev;
 
@@ -463,6 +464,7 @@ nouveau_ttm_tt_create(struct ttm_bo_device *bdev, unsigned long size,
                return ttm_agp_tt_create(bdev, dev->agp->bridge, size,
                                         page_flags, dummy_read);
        }
+#endif
 
        return nouveau_sgdma_create_ttm(bdev, size, page_flags, dummy_read);
 }
index 9a6e2cb..d3595b2 100644 (file)
@@ -355,7 +355,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
         * valid - it's not (rh#613284)
         */
        if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) {
-               if (!(nv_connector->edid = nouveau_acpi_edid(dev, connector))) {
+               if ((nv_connector->edid = nouveau_acpi_edid(dev, connector))) {
                        status = connector_status_connected;
                        goto out;
                }
index 8f98e5a..86124b1 100644 (file)
@@ -290,6 +290,7 @@ nouveau_display_create(struct drm_device *dev)
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_disp *pdisp = nouveau_disp(drm->device);
        struct nouveau_display *disp;
+       u32 pclass = dev->pdev->class >> 8;
        int ret, gen;
 
        disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL);
@@ -360,23 +361,27 @@ nouveau_display_create(struct drm_device *dev)
        drm_kms_helper_poll_init(dev);
        drm_kms_helper_poll_disable(dev);
 
-       if (nv_device(drm->device)->card_type < NV_50)
-               ret = nv04_display_create(dev);
-       else
-       if (nv_device(drm->device)->card_type < NV_D0)
-               ret = nv50_display_create(dev);
-       else
-               ret = nvd0_display_create(dev);
-       if (ret)
-               goto disp_create_err;
-
-       if (dev->mode_config.num_crtc) {
-               ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+       if (nouveau_modeset == 1 ||
+           (nouveau_modeset < 0 && pclass == PCI_CLASS_DISPLAY_VGA)) {
+               if (nv_device(drm->device)->card_type < NV_50)
+                       ret = nv04_display_create(dev);
+               else
+               if (nv_device(drm->device)->card_type < NV_D0)
+                       ret = nv50_display_create(dev);
+               else
+                       ret = nvd0_display_create(dev);
                if (ret)
-                       goto vblank_err;
+                       goto disp_create_err;
+
+               if (dev->mode_config.num_crtc) {
+                       ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+                       if (ret)
+                               goto vblank_err;
+               }
+
+               nouveau_backlight_init(dev);
        }
 
-       nouveau_backlight_init(dev);
        return 0;
 
 vblank_err:
@@ -395,7 +400,8 @@ nouveau_display_destroy(struct drm_device *dev)
        nouveau_backlight_exit(dev);
        drm_vblank_cleanup(dev);
 
-       disp->dtor(dev);
+       if (disp->dtor)
+               disp->dtor(dev);
 
        drm_kms_helper_poll_fini(dev);
        drm_mode_config_cleanup(dev);
@@ -530,9 +536,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 +559,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 ccae8c2..8503b2e 100644 (file)
@@ -63,8 +63,9 @@ MODULE_PARM_DESC(noaccel, "disable kernel/abi16 acceleration");
 static int nouveau_noaccel = 0;
 module_param_named(noaccel, nouveau_noaccel, int, 0400);
 
-MODULE_PARM_DESC(modeset, "enable driver");
-static int nouveau_modeset = -1;
+MODULE_PARM_DESC(modeset, "enable driver (default: auto, "
+                         "0 = disabled, 1 = enabled, 2 = headless)");
+int nouveau_modeset = -1;
 module_param_named(modeset, nouveau_modeset, int, 0400);
 
 static struct drm_driver driver;
@@ -128,7 +129,8 @@ nouveau_accel_init(struct nouveau_drm *drm)
 
        /* initialise synchronisation routines */
        if      (device->card_type < NV_10) ret = nv04_fence_create(drm);
-       else if (device->chipset   <  0x84) ret = nv10_fence_create(drm);
+       else if (device->card_type < NV_50) ret = nv10_fence_create(drm);
+       else if (device->chipset   <  0x84) ret = nv50_fence_create(drm);
        else if (device->card_type < NV_C0) ret = nv84_fence_create(drm);
        else                                ret = nvc0_fence_create(drm);
        if (ret) {
@@ -363,7 +365,8 @@ nouveau_drm_unload(struct drm_device *dev)
 
        nouveau_pm_fini(dev);
 
-       nouveau_display_fini(dev);
+       if (dev->mode_config.num_crtc)
+               nouveau_display_fini(dev);
        nouveau_display_destroy(dev);
 
        nouveau_irq_fini(dev);
@@ -403,13 +406,15 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state)
            pm_state.event == PM_EVENT_PRETHAW)
                return 0;
 
-       NV_INFO(drm, "suspending fbcon...\n");
-       nouveau_fbcon_set_suspend(dev, 1);
+       if (dev->mode_config.num_crtc) {
+               NV_INFO(drm, "suspending fbcon...\n");
+               nouveau_fbcon_set_suspend(dev, 1);
 
-       NV_INFO(drm, "suspending display...\n");
-       ret = nouveau_display_suspend(dev);
-       if (ret)
-               return ret;
+               NV_INFO(drm, "suspending display...\n");
+               ret = nouveau_display_suspend(dev);
+               if (ret)
+                       return ret;
+       }
 
        NV_INFO(drm, "evicting buffers...\n");
        ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM);
@@ -445,8 +450,10 @@ fail_client:
                nouveau_client_init(&cli->base);
        }
 
-       NV_INFO(drm, "resuming display...\n");
-       nouveau_display_resume(dev);
+       if (dev->mode_config.num_crtc) {
+               NV_INFO(drm, "resuming display...\n");
+               nouveau_display_resume(dev);
+       }
        return ret;
 }
 
@@ -486,8 +493,10 @@ nouveau_drm_resume(struct pci_dev *pdev)
        nouveau_irq_postinstall(dev);
        nouveau_pm_resume(dev);
 
-       NV_INFO(drm, "resuming display...\n");
-       nouveau_display_resume(dev);
+       if (dev->mode_config.num_crtc) {
+               NV_INFO(drm, "resuming display...\n");
+               nouveau_display_resume(dev);
+       }
        return 0;
 }
 
@@ -662,9 +671,7 @@ nouveau_drm_init(void)
 #ifdef CONFIG_VGA_CONSOLE
                if (vgacon_text_force())
                        nouveau_modeset = 0;
-               else
 #endif
-                       nouveau_modeset = 1;
        }
 
        if (!nouveau_modeset)
index 8194712..a101699 100644 (file)
@@ -141,4 +141,6 @@ int nouveau_drm_resume(struct pci_dev *);
                nv_info((cli), fmt, ##args);                                   \
 } while (0)
 
+extern int nouveau_modeset;
+
 #endif
index 9ca8afd..1d8cb50 100644 (file)
@@ -61,13 +61,15 @@ nouveau_irq_handler(DRM_IRQ_ARGS)
 
        nv_subdev(pmc)->intr(nv_subdev(pmc));
 
-       if (device->card_type >= NV_D0) {
-               if (nv_rd32(device, 0x000100) & 0x04000000)
-                       nvd0_display_intr(dev);
-       } else
-       if (device->card_type >= NV_50) {
-               if (nv_rd32(device, 0x000100) & 0x04000000)
-                       nv50_display_intr(dev);
+       if (dev->mode_config.num_crtc) {
+               if (device->card_type >= NV_D0) {
+                       if (nv_rd32(device, 0x000100) & 0x04000000)
+                               nvd0_display_intr(dev);
+               } else
+               if (device->card_type >= NV_50) {
+                       if (nv_rd32(device, 0x000100) & 0x04000000)
+                               nv50_display_intr(dev);
+               }
        }
 
        return IRQ_HANDLED;
index 0bf64c9..5566172 100644 (file)
@@ -52,7 +52,7 @@ nouveau_pm_perflvl_aux(struct drm_device *dev, struct nouveau_pm_level *perflvl,
 {
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_pm *pm = nouveau_pm(dev);
-       struct nouveau_therm *therm = nouveau_therm(drm);
+       struct nouveau_therm *therm = nouveau_therm(drm->device);
        int ret;
 
        /*XXX: not on all boards, we should control based on temperature
@@ -64,7 +64,6 @@ nouveau_pm_perflvl_aux(struct drm_device *dev, struct nouveau_pm_level *perflvl,
                ret = therm->fan_set(therm, perflvl->fanspeed);
                if (ret && ret != -ENODEV) {
                        NV_ERROR(drm, "fanspeed set failed: %d\n", ret);
-                       return ret;
                }
        }
 
@@ -706,8 +705,7 @@ nouveau_hwmon_init(struct drm_device *dev)
        struct device *hwmon_dev;
        int ret = 0;
 
-       if (!therm || !therm->temp_get || !therm->attr_get ||
-               !therm->attr_set || therm->temp_get(therm) < 0)
+       if (!therm || !therm->temp_get || !therm->attr_get || !therm->attr_set)
                return -ENODEV;
 
        hwmon_dev = hwmon_device_register(&dev->pdev->dev);
index 347a3bd..64f7020 100644 (file)
@@ -220,7 +220,7 @@ out:
        NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode);
 
        if (blue == 0x18) {
-               NV_INFO(drm, "Load detected on head A\n");
+               NV_DEBUG(drm, "Load detected on head A\n");
                return connector_status_connected;
        }
 
@@ -338,8 +338,8 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
 
        if (nv17_dac_sample_load(encoder) &
            NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) {
-               NV_INFO(drm, "Load detected on output %c\n",
-                       '@' + ffs(dcb->or));
+               NV_DEBUG(drm, "Load detected on output %c\n",
+                        '@' + ffs(dcb->or));
                return connector_status_connected;
        } else {
                return connector_status_disconnected;
@@ -413,9 +413,9 @@ static void nv04_dac_commit(struct drm_encoder *encoder)
 
        helper->dpms(encoder, DRM_MODE_DPMS_ON);
 
-       NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n",
-               drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
-               nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
+       NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
+                drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
+                nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
 }
 
 void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable)
@@ -461,8 +461,8 @@ static void nv04_dac_dpms(struct drm_encoder *encoder, int mode)
                return;
        nv_encoder->last_dpms = mode;
 
-       NV_INFO(drm, "Setting dpms mode %d on vga encoder (output %d)\n",
-                    mode, nv_encoder->dcb->index);
+       NV_DEBUG(drm, "Setting dpms mode %d on vga encoder (output %d)\n",
+                mode, nv_encoder->dcb->index);
 
        nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON);
 }
index da55d76..184cdf8 100644 (file)
@@ -476,9 +476,9 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
 
        helper->dpms(encoder, DRM_MODE_DPMS_ON);
 
-       NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n",
-               drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
-               nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
+       NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
+                drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
+                nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
 }
 
 static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode)
@@ -520,8 +520,8 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode)
                return;
        nv_encoder->last_dpms = mode;
 
-       NV_INFO(drm, "Setting dpms mode %d on lvds encoder (output %d)\n",
-                    mode, nv_encoder->dcb->index);
+       NV_DEBUG(drm, "Setting dpms mode %d on lvds encoder (output %d)\n",
+                mode, nv_encoder->dcb->index);
 
        if (was_powersaving && is_powersaving_dpms(mode))
                return;
@@ -565,8 +565,8 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode)
                return;
        nv_encoder->last_dpms = mode;
 
-       NV_INFO(drm, "Setting dpms mode %d on tmds encoder (output %d)\n",
-                    mode, nv_encoder->dcb->index);
+       NV_DEBUG(drm, "Setting dpms mode %d on tmds encoder (output %d)\n",
+                mode, nv_encoder->dcb->index);
 
        nv04_dfp_update_backlight(encoder, mode);
        nv04_dfp_update_fp_control(encoder, mode);
index 099fbed..62e826a 100644 (file)
@@ -75,8 +75,8 @@ static void nv04_tv_dpms(struct drm_encoder *encoder, int mode)
        struct nv04_mode_state *state = &nv04_display(dev)->mode_reg;
        uint8_t crtc1A;
 
-       NV_INFO(drm, "Setting dpms mode %d on TV encoder (output %d)\n",
-               mode, nv_encoder->dcb->index);
+       NV_DEBUG(drm, "Setting dpms mode %d on TV encoder (output %d)\n",
+                mode, nv_encoder->dcb->index);
 
        state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK);
 
@@ -167,9 +167,8 @@ static void nv04_tv_commit(struct drm_encoder *encoder)
 
        helper->dpms(encoder, DRM_MODE_DPMS_ON);
 
-       NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n",
-                     drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index,
-                     '@' + ffs(nv_encoder->dcb->or));
+       NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
+                drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
 }
 
 static void nv04_tv_destroy(struct drm_encoder *encoder)
index 96184d0..24d932f 100644 (file)
@@ -1690,41 +1690,29 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
                }
                /* all other cases */
                pll_in_use = radeon_get_pll_use_mask(crtc);
-               if (!(pll_in_use & (1 << ATOM_PPLL2)))
-                       return ATOM_PPLL2;
                if (!(pll_in_use & (1 << ATOM_PPLL1)))
                        return ATOM_PPLL1;
+               if (!(pll_in_use & (1 << ATOM_PPLL2)))
+                       return ATOM_PPLL2;
                DRM_ERROR("unable to allocate a PPLL\n");
                return ATOM_PPLL_INVALID;
        } else {
-               if (ASIC_IS_AVIVO(rdev)) {
-                       /* in DP mode, the DP ref clock can come from either PPLL
-                        * depending on the asic:
-                        * DCE3: PPLL1 or PPLL2
-                        */
-                       if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) {
-                               /* use the same PPLL for all DP monitors */
-                               pll = radeon_get_shared_dp_ppll(crtc);
-                               if (pll != ATOM_PPLL_INVALID)
-                                       return pll;
-                       } else {
-                               /* use the same PPLL for all monitors with the same clock */
-                               pll = radeon_get_shared_nondp_ppll(crtc);
-                               if (pll != ATOM_PPLL_INVALID)
-                                       return pll;
-                       }
-                       /* all other cases */
-                       pll_in_use = radeon_get_pll_use_mask(crtc);
-                       if (!(pll_in_use & (1 << ATOM_PPLL2)))
-                               return ATOM_PPLL2;
-                       if (!(pll_in_use & (1 << ATOM_PPLL1)))
-                               return ATOM_PPLL1;
-                       DRM_ERROR("unable to allocate a PPLL\n");
-                       return ATOM_PPLL_INVALID;
-               } else {
-                       /* on pre-R5xx asics, the crtc to pll mapping is hardcoded */
-                       return radeon_crtc->crtc_id;
-               }
+               /* on pre-R5xx asics, the crtc to pll mapping is hardcoded */
+               /* some atombios (observed in some DCE2/DCE3) code have a bug,
+                * the matching btw pll and crtc is done through
+                * PCLK_CRTC[1|2]_CNTL (0x480/0x484) but atombios code use the
+                * pll (1 or 2) to select which register to write. ie if using
+                * pll1 it will use PCLK_CRTC1_CNTL (0x480) and if using pll2
+                * it will use PCLK_CRTC2_CNTL (0x484), it then use crtc id to
+                * choose which value to write. Which is reverse order from
+                * register logic. So only case that works is when pllid is
+                * same as crtcid or when both pll and crtc are enabled and
+                * both use same clock.
+                *
+                * So just return crtc id as if crtc and pll were hard linked
+                * together even if they aren't
+                */
+               return radeon_crtc->crtc_id;
        }
 }
 
index 49cbb37..010bae1 100644 (file)
@@ -184,6 +184,7 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
        struct radeon_backlight_privdata *pdata;
        struct radeon_encoder_atom_dig *dig;
        u8 backlight_level;
+       char bl_name[16];
 
        if (!radeon_encoder->enc_priv)
                return;
@@ -203,7 +204,9 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
        memset(&props, 0, sizeof(props));
        props.max_brightness = RADEON_MAX_BL_LEVEL;
        props.type = BACKLIGHT_RAW;
-       bd = backlight_device_register("radeon_bl", &drm_connector->kdev,
+       snprintf(bl_name, sizeof(bl_name),
+                "radeon_bl%d", dev->primary->index);
+       bd = backlight_device_register(bl_name, &drm_connector->kdev,
                                       pdata, &radeon_atom_backlight_ops, &props);
        if (IS_ERR(bd)) {
                DRM_ERROR("Backlight registration failed\n");
@@ -1622,7 +1625,7 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
                        atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
                        atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
                        /* some early dce3.2 boards have a bug in their transmitter control table */
-                       if ((rdev->family != CHIP_RV710) || (rdev->family != CHIP_RV730))
+                       if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730))
                                atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
                }
                if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
index a1f49c5..219942c 100644 (file)
@@ -1330,6 +1330,8 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav
                                        break;
                                udelay(1);
                        }
+               } else {
+                       save->crtc_enabled[i] = false;
                }
        }
 
@@ -1372,7 +1374,7 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s
        WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN);
 
        for (i = 0; i < rdev->num_crtc; i++) {
-               if (save->crtc_enabled) {
+               if (save->crtc_enabled[i]) {
                        if (ASIC_IS_DCE6(rdev)) {
                                tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]);
                                tmp |= EVERGREEN_CRTC_BLANK_DATA_EN;
@@ -3431,9 +3433,14 @@ void evergreen_pcie_gen2_enable(struct radeon_device *rdev)
        if (!(mask & DRM_PCIE_SPEED_50))
                return;
 
+       speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
+       if (speed_cntl & LC_CURRENT_DATA_RATE) {
+               DRM_INFO("PCIE gen 2 link speeds already enabled\n");
+               return;
+       }
+
        DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n");
 
-       speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
        if ((speed_cntl & LC_OTHER_SIDE_EVER_SENT_GEN2) ||
            (speed_cntl & LC_OTHER_SIDE_SUPPORTS_GEN2)) {
 
index 573ed1b..c042e49 100644 (file)
@@ -264,7 +264,7 @@ static int evergreen_surface_check_2d(struct radeon_cs_parser *p,
        /* macro tile width & height */
        palign = (8 * surf->bankw * track->npipes) * surf->mtilea;
        halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea;
-       mtileb = (palign / 8) * (halign / 8) * tileb;;
+       mtileb = (palign / 8) * (halign / 8) * tileb;
        mtile_pr = surf->nbx / palign;
        mtile_ps = (mtile_pr * surf->nby) / halign;
        surf->layer_size = mtile_ps * mtileb * slice_pt;
@@ -2725,6 +2725,9 @@ static bool evergreen_vm_reg_valid(u32 reg)
        /* check config regs */
        switch (reg) {
        case GRBM_GFX_INDEX:
+       case CP_STRMOUT_CNTL:
+       case CP_COHER_CNTL:
+       case CP_COHER_SIZE:
        case VGT_VTX_VECT_EJECT_REG:
        case VGT_CACHE_INVALIDATION:
        case VGT_GS_VERTEX_REUSE:
@@ -2829,6 +2832,7 @@ static bool evergreen_vm_reg_valid(u32 reg)
        case CAYMAN_SQ_EX_ALLOC_TABLE_SLOTS:
                return true;
        default:
+               DRM_ERROR("Invalid register 0x%x in CS\n", reg);
                return false;
        }
 }
index df542f1..2bc0f6a 100644 (file)
 #define                FB_READ_EN                                      (1 << 0)
 #define                FB_WRITE_EN                                     (1 << 1)
 
+#define        CP_STRMOUT_CNTL                                 0x84FC
+
+#define        CP_COHER_CNTL                                   0x85F0
+#define        CP_COHER_SIZE                                   0x85F4
 #define        CP_COHER_BASE                                   0x85F8
 #define        CP_STALLED_STAT1                        0x8674
 #define        CP_STALLED_STAT2                        0x8678
index 8bcb554..81e6a56 100644 (file)
@@ -770,9 +770,13 @@ static int cayman_pcie_gart_enable(struct radeon_device *rdev)
        WREG32(0x15DC, 0);
 
        /* empty context1-7 */
+       /* Assign the pt base to something valid for now; the pts used for
+        * the VMs are determined by the application and setup and assigned
+        * on the fly in the vm part of radeon_gart.c
+        */
        for (i = 1; i < 8; i++) {
                WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (i << 2), 0);
-               WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2), 0);
+               WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2), rdev->vm_manager.max_pfn);
                WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2),
                        rdev->gart.table_addr >> 12);
        }
@@ -1534,26 +1538,31 @@ void cayman_vm_set_page(struct radeon_device *rdev, uint64_t pe,
 {
        struct radeon_ring *ring = &rdev->ring[rdev->asic->vm.pt_ring_index];
        uint32_t r600_flags = cayman_vm_page_flags(rdev, flags);
-       int i;
 
-       radeon_ring_write(ring, PACKET3(PACKET3_ME_WRITE, 1 + count * 2));
-       radeon_ring_write(ring, pe);
-       radeon_ring_write(ring, upper_32_bits(pe) & 0xff);
-       for (i = 0; i < count; ++i) {
-               uint64_t value = 0;
-               if (flags & RADEON_VM_PAGE_SYSTEM) {
-                       value = radeon_vm_map_gart(rdev, addr);
-                       value &= 0xFFFFFFFFFFFFF000ULL;
-                       addr += incr;
-
-               } else if (flags & RADEON_VM_PAGE_VALID) {
-                       value = addr;
-                       addr += incr;
-               }
+       while (count) {
+               unsigned ndw = 1 + count * 2;
+               if (ndw > 0x3FFF)
+                       ndw = 0x3FFF;
+
+               radeon_ring_write(ring, PACKET3(PACKET3_ME_WRITE, ndw));
+               radeon_ring_write(ring, pe);
+               radeon_ring_write(ring, upper_32_bits(pe) & 0xff);
+               for (; ndw > 1; ndw -= 2, --count, pe += 8) {
+                       uint64_t value = 0;
+                       if (flags & RADEON_VM_PAGE_SYSTEM) {
+                               value = radeon_vm_map_gart(rdev, addr);
+                               value &= 0xFFFFFFFFFFFFF000ULL;
+                               addr += incr;
+
+                       } else if (flags & RADEON_VM_PAGE_VALID) {
+                               value = addr;
+                               addr += incr;
+                       }
 
-               value |= r600_flags;
-               radeon_ring_write(ring, value);
-               radeon_ring_write(ring, upper_32_bits(value));
+                       value |= r600_flags;
+                       radeon_ring_write(ring, value);
+                       radeon_ring_write(ring, upper_32_bits(value));
+               }
        }
 }
 
@@ -1572,12 +1581,6 @@ void cayman_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
        if (vm == NULL)
                return;
 
-       radeon_ring_write(ring, PACKET0(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (vm->id << 2), 0));
-       radeon_ring_write(ring, 0);
-
-       radeon_ring_write(ring, PACKET0(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (vm->id << 2), 0));
-       radeon_ring_write(ring, vm->last_pfn);
-
        radeon_ring_write(ring, PACKET0(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm->id << 2), 0));
        radeon_ring_write(ring, vm->pd_gpu_addr >> 12);
 
@@ -1588,4 +1591,8 @@ void cayman_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
        /* bits 0-7 are the VM contexts0-7 */
        radeon_ring_write(ring, PACKET0(VM_INVALIDATE_REQUEST, 0));
        radeon_ring_write(ring, 1 << vm->id);
+
+       /* sync PFP to ME, otherwise we might get invalid PFP reads */
+       radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0));
+       radeon_ring_write(ring, 0x0);
 }
index 2423d1b..cbef681 100644 (file)
 #define        PACKET3_MPEG_INDEX                              0x3A
 #define        PACKET3_WAIT_REG_MEM                            0x3C
 #define        PACKET3_MEM_WRITE                               0x3D
+#define        PACKET3_PFP_SYNC_ME                             0x42
 #define        PACKET3_SURFACE_SYNC                            0x43
 #              define PACKET3_CB0_DEST_BASE_ENA    (1 << 6)
 #              define PACKET3_CB1_DEST_BASE_ENA    (1 << 7)
index 70c800f..cda280d 100644 (file)
@@ -3703,6 +3703,12 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev)
        if (!(mask & DRM_PCIE_SPEED_50))
                return;
 
+       speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
+       if (speed_cntl & LC_CURRENT_DATA_RATE) {
+               DRM_INFO("PCIE gen 2 link speeds already enabled\n");
+               return;
+       }
+
        DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n");
 
        /* 55 nm r6xx asics */
index b04c064..8c42d54 100644 (file)
@@ -663,9 +663,14 @@ struct radeon_vm {
        struct list_head                list;
        struct list_head                va;
        unsigned                        id;
-       unsigned                        last_pfn;
-       u64                             pd_gpu_addr;
-       struct radeon_sa_bo             *sa_bo;
+
+       /* contains the page directory */
+       struct radeon_sa_bo             *page_directory;
+       uint64_t                        pd_gpu_addr;
+
+       /* array of page tables, one for each page directory entry */
+       struct radeon_sa_bo             **page_tables;
+
        struct mutex                    mutex;
        /* last fence for cs using this vm */
        struct radeon_fence             *fence;
@@ -1843,9 +1848,10 @@ extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size
  */
 int radeon_vm_manager_init(struct radeon_device *rdev);
 void radeon_vm_manager_fini(struct radeon_device *rdev);
-int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm);
+void radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm);
 void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm);
 int radeon_vm_alloc_pt(struct radeon_device *rdev, struct radeon_vm *vm);
+void radeon_vm_add_to_lru(struct radeon_device *rdev, struct radeon_vm *vm);
 struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev,
                                       struct radeon_vm *vm, int ring);
 void radeon_vm_fence(struct radeon_device *rdev,
index b0a5688..196d28d 100644 (file)
@@ -201,7 +201,7 @@ static int radeon_atif_verify_interface(acpi_handle handle,
 
        size = *(u16 *) info->buffer.pointer;
        if (size < 12) {
-               DRM_INFO("ATIF buffer is too small: %lu\n", size);
+               DRM_INFO("ATIF buffer is too small: %zu\n", size);
                err = -EINVAL;
                goto out;
        }
@@ -370,6 +370,7 @@ int radeon_atif_handler(struct radeon_device *rdev,
 
                        radeon_set_backlight_level(rdev, enc, req.backlight_level);
 
+#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
                        if (rdev->is_atom_bios) {
                                struct radeon_encoder_atom_dig *dig = enc->enc_priv;
                                backlight_force_update(dig->bl_dev,
@@ -379,6 +380,7 @@ int radeon_atif_handler(struct radeon_device *rdev,
                                backlight_force_update(dig->bl_dev,
                                                       BACKLIGHT_UPDATE_HOTKEY);
                        }
+#endif
                }
        }
        /* TODO: check other events */
@@ -485,7 +487,7 @@ static int radeon_atcs_verify_interface(acpi_handle handle,
 
        size = *(u16 *) info->buffer.pointer;
        if (size < 8) {
-               DRM_INFO("ATCS buffer is too small: %lu\n", size);
+               DRM_INFO("ATCS buffer is too small: %zu\n", size);
                err = -EINVAL;
                goto out;
        }
index 10ea17a..4243334 100644 (file)
@@ -69,9 +69,12 @@ static struct radeon_agpmode_quirk radeon_agpmode_quirk_list[] = {
        /* Intel 82830 830 Chipset Host Bridge / Mobility M6 LY Needs AGPMode 2 (fdo #17360)*/
        { PCI_VENDOR_ID_INTEL, 0x3575, PCI_VENDOR_ID_ATI, 0x4c59,
                PCI_VENDOR_ID_DELL, 0x00e3, 2},
-       /* Intel 82852/82855 host bridge / Mobility FireGL 9000 R250 Needs AGPMode 1 (lp #296617) */
+       /* Intel 82852/82855 host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 (lp #296617) */
        { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4c66,
                PCI_VENDOR_ID_DELL, 0x0149, 1},
+       /* Intel 82855PM host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 for suspend/resume */
+       { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c66,
+               PCI_VENDOR_ID_IBM, 0x0531, 1},
        /* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (deb #467460) */
        { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50,
                0x1025, 0x0061, 1},
index 582e994..15f5ded 100644 (file)
@@ -87,7 +87,7 @@ static union acpi_object *radeon_atpx_call(acpi_handle handle, int function,
                atpx_arg_elements[1].integer.value = 0;
        }
 
-       status = acpi_evaluate_object(handle, "ATPX", &atpx_arg, &buffer);
+       status = acpi_evaluate_object(handle, NULL, &atpx_arg, &buffer);
 
        /* Fail only if calling the method fails and ATPX is supported */
        if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
@@ -148,7 +148,7 @@ static int radeon_atpx_verify_interface(struct radeon_atpx *atpx)
 
        size = *(u16 *) info->buffer.pointer;
        if (size < 8) {
-               printk("ATPX buffer is too small: %lu\n", size);
+               printk("ATPX buffer is too small: %zu\n", size);
                err = -EINVAL;
                goto out;
        }
@@ -352,9 +352,9 @@ static int radeon_atpx_switchto(enum vga_switcheroo_client_id id)
 }
 
 /**
- * radeon_atpx_switchto - switch to the requested GPU
+ * radeon_atpx_power_state - power down/up the requested GPU
  *
- * @id: GPU to switch to
+ * @id: GPU to power down/up
  * @state: requested power state (0 = off, 1 = on)
  *
  * Execute the necessary ATPX function to power down/up the discrete GPU
@@ -373,11 +373,11 @@ static int radeon_atpx_power_state(enum vga_switcheroo_client_id id,
 }
 
 /**
- * radeon_atpx_pci_probe_handle - look up the ATRM and ATPX handles
+ * radeon_atpx_pci_probe_handle - look up the ATPX handle
  *
  * @pdev: pci device
  *
- * Look up the ATPX and ATRM handles (all asics).
+ * Look up the ATPX handles (all asics).
  * Returns true if the handles are found, false if not.
  */
 static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)
index 67cfc17..b884c36 100644 (file)
@@ -941,7 +941,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
        struct drm_mode_object *obj;
        int i;
        enum drm_connector_status ret = connector_status_disconnected;
-       bool dret = false;
+       bool dret = false, broken_edid = false;
 
        if (!force && radeon_check_hpd_status_unchanged(connector))
                return connector->status;
@@ -965,6 +965,9 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
                                ret = connector_status_disconnected;
                                DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector));
                                radeon_connector->ddc_bus = NULL;
+                       } else {
+                               ret = connector_status_connected;
+                               broken_edid = true; /* defer use_digital to later */
                        }
                } else {
                        radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
@@ -1047,13 +1050,24 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
 
                        encoder_funcs = encoder->helper_private;
                        if (encoder_funcs->detect) {
-                               if (ret != connector_status_connected) {
-                                       ret = encoder_funcs->detect(encoder, connector);
-                                       if (ret == connector_status_connected) {
-                                               radeon_connector->use_digital = false;
+                               if (!broken_edid) {
+                                       if (ret != connector_status_connected) {
+                                               /* deal with analog monitors without DDC */
+                                               ret = encoder_funcs->detect(encoder, connector);
+                                               if (ret == connector_status_connected) {
+                                                       radeon_connector->use_digital = false;
+                                               }
+                                               if (ret != connector_status_disconnected)
+                                                       radeon_connector->detected_by_load = true;
                                        }
-                                       if (ret != connector_status_disconnected)
-                                               radeon_connector->detected_by_load = true;
+                               } else {
+                                       enum drm_connector_status lret;
+                                       /* assume digital unless load detected otherwise */
+                                       radeon_connector->use_digital = true;
+                                       lret = encoder_funcs->detect(encoder, connector);
+                                       DRM_DEBUG_KMS("load_detect %x returned: %x\n",encoder->encoder_type,lret);
+                                       if (lret == connector_status_connected)
+                                               radeon_connector->use_digital = false;
                                }
                                break;
                        }
index cb7b7c0..41672cc 100644 (file)
@@ -478,6 +478,7 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev,
        }
 
 out:
+       radeon_vm_add_to_lru(rdev, vm);
        mutex_unlock(&vm->mutex);
        mutex_unlock(&rdev->vm_manager.lock);
        return r;
index 64a4264..e2f5f88 100644 (file)
@@ -355,6 +355,8 @@ int radeon_wb_init(struct radeon_device *rdev)
  */
 void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base)
 {
+       uint64_t limit = (uint64_t)radeon_vram_limit << 20;
+
        mc->vram_start = base;
        if (mc->mc_vram_size > (0xFFFFFFFF - base + 1)) {
                dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n");
@@ -368,8 +370,8 @@ void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64
                mc->mc_vram_size = mc->aper_size;
        }
        mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
-       if (radeon_vram_limit && radeon_vram_limit < mc->real_vram_size)
-               mc->real_vram_size = radeon_vram_limit;
+       if (limit && limit < mc->real_vram_size)
+               mc->real_vram_size = limit;
        dev_info(rdev->dev, "VRAM: %lluM 0x%016llX - 0x%016llX (%lluM used)\n",
                        mc->mc_vram_size >> 20, mc->vram_start,
                        mc->vram_end, mc->real_vram_size >> 20);
@@ -835,6 +837,19 @@ static unsigned int radeon_vga_set_decode(void *cookie, bool state)
 }
 
 /**
+ * radeon_check_pot_argument - check that argument is a power of two
+ *
+ * @arg: value to check
+ *
+ * Validates that a certain argument is a power of two (all asics).
+ * Returns true if argument is valid.
+ */
+static bool radeon_check_pot_argument(int arg)
+{
+       return (arg & (arg - 1)) == 0;
+}
+
+/**
  * radeon_check_arguments - validate module params
  *
  * @rdev: radeon_device pointer
@@ -845,52 +860,25 @@ static unsigned int radeon_vga_set_decode(void *cookie, bool state)
 static void radeon_check_arguments(struct radeon_device *rdev)
 {
        /* vramlimit must be a power of two */
-       switch (radeon_vram_limit) {
-       case 0:
-       case 4:
-       case 8:
-       case 16:
-       case 32:
-       case 64:
-       case 128:
-       case 256:
-       case 512:
-       case 1024:
-       case 2048:
-       case 4096:
-               break;
-       default:
+       if (!radeon_check_pot_argument(radeon_vram_limit)) {
                dev_warn(rdev->dev, "vram limit (%d) must be a power of 2\n",
                                radeon_vram_limit);
                radeon_vram_limit = 0;
-               break;
        }
-       radeon_vram_limit = radeon_vram_limit << 20;
+
        /* gtt size must be power of two and greater or equal to 32M */
-       switch (radeon_gart_size) {
-       case 4:
-       case 8:
-       case 16:
+       if (radeon_gart_size < 32) {
                dev_warn(rdev->dev, "gart size (%d) too small forcing to 512M\n",
                                radeon_gart_size);
                radeon_gart_size = 512;
-               break;
-       case 32:
-       case 64:
-       case 128:
-       case 256:
-       case 512:
-       case 1024:
-       case 2048:
-       case 4096:
-               break;
-       default:
+
+       } else if (!radeon_check_pot_argument(radeon_gart_size)) {
                dev_warn(rdev->dev, "gart size (%d) must be a power of 2\n",
                                radeon_gart_size);
                radeon_gart_size = 512;
-               break;
        }
-       rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+       rdev->mc.gtt_size = (uint64_t)radeon_gart_size << 20;
+
        /* AGP mode can only be -1, 1, 2, 4, 8 */
        switch (radeon_agpmode) {
        case -1:
@@ -1018,6 +1006,10 @@ int radeon_device_init(struct radeon_device *rdev,
                return r;
        /* initialize vm here */
        mutex_init(&rdev->vm_manager.lock);
+       /* Adjust VM size here.
+        * Currently set to 4GB ((1 << 20) 4k pages).
+        * Max GPUVM size for cayman and SI is 40 bits.
+        */
        rdev->vm_manager.max_pfn = 1 << 20;
        INIT_LIST_HEAD(&rdev->vm_manager.lru_vm);
 
index f0c06d1..4debd60 100644 (file)
@@ -355,14 +355,13 @@ int radeon_gart_init(struct radeon_device *rdev)
        DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n",
                 rdev->gart.num_cpu_pages, rdev->gart.num_gpu_pages);
        /* Allocate pages table */
-       rdev->gart.pages = kzalloc(sizeof(void *) * rdev->gart.num_cpu_pages,
-                                  GFP_KERNEL);
+       rdev->gart.pages = vzalloc(sizeof(void *) * rdev->gart.num_cpu_pages);
        if (rdev->gart.pages == NULL) {
                radeon_gart_fini(rdev);
                return -ENOMEM;
        }
-       rdev->gart.pages_addr = kzalloc(sizeof(dma_addr_t) *
-                                       rdev->gart.num_cpu_pages, GFP_KERNEL);
+       rdev->gart.pages_addr = vzalloc(sizeof(dma_addr_t) *
+                                       rdev->gart.num_cpu_pages);
        if (rdev->gart.pages_addr == NULL) {
                radeon_gart_fini(rdev);
                return -ENOMEM;
@@ -388,8 +387,8 @@ void radeon_gart_fini(struct radeon_device *rdev)
                radeon_gart_unbind(rdev, 0, rdev->gart.num_cpu_pages);
        }
        rdev->gart.ready = false;
-       kfree(rdev->gart.pages);
-       kfree(rdev->gart.pages_addr);
+       vfree(rdev->gart.pages);
+       vfree(rdev->gart.pages_addr);
        rdev->gart.pages = NULL;
        rdev->gart.pages_addr = NULL;
 
@@ -423,6 +422,18 @@ void radeon_gart_fini(struct radeon_device *rdev)
  */
 
 /**
+ * radeon_vm_num_pde - return the number of page directory entries
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Calculate the number of page directory entries (cayman+).
+ */
+static unsigned radeon_vm_num_pdes(struct radeon_device *rdev)
+{
+       return rdev->vm_manager.max_pfn >> RADEON_VM_BLOCK_SIZE;
+}
+
+/**
  * radeon_vm_directory_size - returns the size of the page directory in bytes
  *
  * @rdev: radeon_device pointer
@@ -431,7 +442,7 @@ void radeon_gart_fini(struct radeon_device *rdev)
  */
 static unsigned radeon_vm_directory_size(struct radeon_device *rdev)
 {
-       return (rdev->vm_manager.max_pfn >> RADEON_VM_BLOCK_SIZE) * 8;
+       return RADEON_GPU_PAGE_ALIGN(radeon_vm_num_pdes(rdev) * 8);
 }
 
 /**
@@ -451,11 +462,11 @@ int radeon_vm_manager_init(struct radeon_device *rdev)
 
        if (!rdev->vm_manager.enabled) {
                /* allocate enough for 2 full VM pts */
-               size = RADEON_GPU_PAGE_ALIGN(radeon_vm_directory_size(rdev));
-               size += RADEON_GPU_PAGE_ALIGN(rdev->vm_manager.max_pfn * 8);
+               size = radeon_vm_directory_size(rdev);
+               size += rdev->vm_manager.max_pfn * 8;
                size *= 2;
                r = radeon_sa_bo_manager_init(rdev, &rdev->vm_manager.sa_manager,
-                                             size,
+                                             RADEON_GPU_PAGE_ALIGN(size),
                                              RADEON_GEM_DOMAIN_VRAM);
                if (r) {
                        dev_err(rdev->dev, "failed to allocate vm bo (%dKB)\n",
@@ -476,7 +487,7 @@ int radeon_vm_manager_init(struct radeon_device *rdev)
 
        /* restore page table */
        list_for_each_entry(vm, &rdev->vm_manager.lru_vm, list) {
-               if (vm->sa_bo == NULL)
+               if (vm->page_directory == NULL)
                        continue;
 
                list_for_each_entry(bo_va, &vm->va, vm_list) {
@@ -500,16 +511,25 @@ static void radeon_vm_free_pt(struct radeon_device *rdev,
                                    struct radeon_vm *vm)
 {
        struct radeon_bo_va *bo_va;
+       int i;
 
-       if (!vm->sa_bo)
+       if (!vm->page_directory)
                return;
 
        list_del_init(&vm->list);
-       radeon_sa_bo_free(rdev, &vm->sa_bo, vm->fence);
+       radeon_sa_bo_free(rdev, &vm->page_directory, vm->fence);
 
        list_for_each_entry(bo_va, &vm->va, vm_list) {
                bo_va->valid = false;
        }
+
+       if (vm->page_tables == NULL)
+               return;
+
+       for (i = 0; i < radeon_vm_num_pdes(rdev); i++)
+               radeon_sa_bo_free(rdev, &vm->page_tables[i], vm->fence);
+
+       kfree(vm->page_tables);
 }
 
 /**
@@ -546,63 +566,106 @@ void radeon_vm_manager_fini(struct radeon_device *rdev)
 }
 
 /**
+ * radeon_vm_evict - evict page table to make room for new one
+ *
+ * @rdev: radeon_device pointer
+ * @vm: VM we want to allocate something for
+ *
+ * Evict a VM from the lru, making sure that it isn't @vm. (cayman+).
+ * Returns 0 for success, -ENOMEM for failure.
+ *
+ * Global and local mutex must be locked!
+ */
+static int radeon_vm_evict(struct radeon_device *rdev, struct radeon_vm *vm)
+{
+       struct radeon_vm *vm_evict;
+
+       if (list_empty(&rdev->vm_manager.lru_vm))
+               return -ENOMEM;
+
+       vm_evict = list_first_entry(&rdev->vm_manager.lru_vm,
+                                   struct radeon_vm, list);
+       if (vm_evict == vm)
+               return -ENOMEM;
+
+       mutex_lock(&vm_evict->mutex);
+       radeon_vm_free_pt(rdev, vm_evict);
+       mutex_unlock(&vm_evict->mutex);
+       return 0;
+}
+
+/**
  * radeon_vm_alloc_pt - allocates a page table for a VM
  *
  * @rdev: radeon_device pointer
  * @vm: vm to bind
  *
  * Allocate a page table for the requested vm (cayman+).
- * Also starts to populate the page table.
  * Returns 0 for success, error for failure.
  *
  * Global and local mutex must be locked!
  */
 int radeon_vm_alloc_pt(struct radeon_device *rdev, struct radeon_vm *vm)
 {
-       struct radeon_vm *vm_evict;
-       int r;
+       unsigned pd_size, pts_size;
        u64 *pd_addr;
-       int tables_size;
+       int r;
 
        if (vm == NULL) {
                return -EINVAL;
        }
 
-       /* allocate enough to cover the current VM size */
-       tables_size = RADEON_GPU_PAGE_ALIGN(radeon_vm_directory_size(rdev));
-       tables_size += RADEON_GPU_PAGE_ALIGN(vm->last_pfn * 8);
-
-       if (vm->sa_bo != NULL) {
-               /* update lru */
-               list_del_init(&vm->list);
-               list_add_tail(&vm->list, &rdev->vm_manager.lru_vm);
+       if (vm->page_directory != NULL) {
                return 0;
        }
 
 retry:
-       r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager, &vm->sa_bo,
-                            tables_size, RADEON_GPU_PAGE_SIZE, false);
+       pd_size = RADEON_GPU_PAGE_ALIGN(radeon_vm_directory_size(rdev));
+       r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager,
+                            &vm->page_directory, pd_size,
+                            RADEON_GPU_PAGE_SIZE, false);
        if (r == -ENOMEM) {
-               if (list_empty(&rdev->vm_manager.lru_vm)) {
+               r = radeon_vm_evict(rdev, vm);
+               if (r)
                        return r;
-               }
-               vm_evict = list_first_entry(&rdev->vm_manager.lru_vm, struct radeon_vm, list);
-               mutex_lock(&vm_evict->mutex);
-               radeon_vm_free_pt(rdev, vm_evict);
-               mutex_unlock(&vm_evict->mutex);
                goto retry;
 
        } else if (r) {
                return r;
        }
 
-       pd_addr = radeon_sa_bo_cpu_addr(vm->sa_bo);
-       vm->pd_gpu_addr = radeon_sa_bo_gpu_addr(vm->sa_bo);
-       memset(pd_addr, 0, tables_size);
+       vm->pd_gpu_addr = radeon_sa_bo_gpu_addr(vm->page_directory);
+
+       /* Initially clear the page directory */
+       pd_addr = radeon_sa_bo_cpu_addr(vm->page_directory);
+       memset(pd_addr, 0, pd_size);
+
+       pts_size = radeon_vm_num_pdes(rdev) * sizeof(struct radeon_sa_bo *);
+       vm->page_tables = kzalloc(pts_size, GFP_KERNEL);
+
+       if (vm->page_tables == NULL) {
+               DRM_ERROR("Cannot allocate memory for page table array\n");
+               radeon_sa_bo_free(rdev, &vm->page_directory, vm->fence);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
 
+/**
+ * radeon_vm_add_to_lru - add VMs page table to LRU list
+ *
+ * @rdev: radeon_device pointer
+ * @vm: vm to add to LRU
+ *
+ * Add the allocated page table to the LRU list (cayman+).
+ *
+ * Global mutex must be locked!
+ */
+void radeon_vm_add_to_lru(struct radeon_device *rdev, struct radeon_vm *vm)
+{
+       list_del_init(&vm->list);
        list_add_tail(&vm->list, &rdev->vm_manager.lru_vm);
-       return radeon_vm_bo_update_pte(rdev, vm, rdev->ring_tmp_bo.bo,
-                                      &rdev->ring_tmp_bo.bo->tbo.mem);
 }
 
 /**
@@ -793,20 +856,6 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,
        }
 
        mutex_lock(&vm->mutex);
-       if (last_pfn > vm->last_pfn) {
-               /* release mutex and lock in right order */
-               mutex_unlock(&vm->mutex);
-               mutex_lock(&rdev->vm_manager.lock);
-               mutex_lock(&vm->mutex);
-               /* and check again */
-               if (last_pfn > vm->last_pfn) {
-                       /* grow va space 32M by 32M */
-                       unsigned align = ((32 << 20) >> 12) - 1;
-                       radeon_vm_free_pt(rdev, vm);
-                       vm->last_pfn = (last_pfn + align) & ~align;
-               }
-               mutex_unlock(&rdev->vm_manager.lock);
-       }
        head = &vm->va;
        last_offset = 0;
        list_for_each_entry(tmp, &vm->va, vm_list) {
@@ -865,6 +914,154 @@ uint64_t radeon_vm_map_gart(struct radeon_device *rdev, uint64_t addr)
 }
 
 /**
+ * radeon_vm_update_pdes - make sure that page directory is valid
+ *
+ * @rdev: radeon_device pointer
+ * @vm: requested vm
+ * @start: start of GPU address range
+ * @end: end of GPU address range
+ *
+ * Allocates new page tables if necessary
+ * and updates the page directory (cayman+).
+ * Returns 0 for success, error for failure.
+ *
+ * Global and local mutex must be locked!
+ */
+static int radeon_vm_update_pdes(struct radeon_device *rdev,
+                                struct radeon_vm *vm,
+                                uint64_t start, uint64_t end)
+{
+       static const uint32_t incr = RADEON_VM_PTE_COUNT * 8;
+
+       uint64_t last_pde = ~0, last_pt = ~0;
+       unsigned count = 0;
+       uint64_t pt_idx;
+       int r;
+
+       start = (start / RADEON_GPU_PAGE_SIZE) >> RADEON_VM_BLOCK_SIZE;
+       end = (end / RADEON_GPU_PAGE_SIZE) >> RADEON_VM_BLOCK_SIZE;
+
+       /* walk over the address space and update the page directory */
+       for (pt_idx = start; pt_idx <= end; ++pt_idx) {
+               uint64_t pde, pt;
+
+               if (vm->page_tables[pt_idx])
+                       continue;
+
+retry:
+               r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager,
+                                    &vm->page_tables[pt_idx],
+                                    RADEON_VM_PTE_COUNT * 8,
+                                    RADEON_GPU_PAGE_SIZE, false);
+
+               if (r == -ENOMEM) {
+                       r = radeon_vm_evict(rdev, vm);
+                       if (r)
+                               return r;
+                       goto retry;
+               } else if (r) {
+                       return r;
+               }
+
+               pde = vm->pd_gpu_addr + pt_idx * 8;
+
+               pt = radeon_sa_bo_gpu_addr(vm->page_tables[pt_idx]);
+
+               if (((last_pde + 8 * count) != pde) ||
+                   ((last_pt + incr * count) != pt)) {
+
+                       if (count) {
+                               radeon_asic_vm_set_page(rdev, last_pde,
+                                                       last_pt, count, incr,
+                                                       RADEON_VM_PAGE_VALID);
+                       }
+
+                       count = 1;
+                       last_pde = pde;
+                       last_pt = pt;
+               } else {
+                       ++count;
+               }
+       }
+
+       if (count) {
+               radeon_asic_vm_set_page(rdev, last_pde, last_pt, count,
+                                       incr, RADEON_VM_PAGE_VALID);
+
+       }
+
+       return 0;
+}
+
+/**
+ * radeon_vm_update_ptes - make sure that page tables are valid
+ *
+ * @rdev: radeon_device pointer
+ * @vm: requested vm
+ * @start: start of GPU address range
+ * @end: end of GPU address range
+ * @dst: destination address to map to
+ * @flags: mapping flags
+ *
+ * Update the page tables in the range @start - @end (cayman+).
+ *
+ * Global and local mutex must be locked!
+ */
+static void radeon_vm_update_ptes(struct radeon_device *rdev,
+                                 struct radeon_vm *vm,
+                                 uint64_t start, uint64_t end,
+                                 uint64_t dst, uint32_t flags)
+{
+       static const uint64_t mask = RADEON_VM_PTE_COUNT - 1;
+
+       uint64_t last_pte = ~0, last_dst = ~0;
+       unsigned count = 0;
+       uint64_t addr;
+
+       start = start / RADEON_GPU_PAGE_SIZE;
+       end = end / RADEON_GPU_PAGE_SIZE;
+
+       /* walk over the address space and update the page tables */
+       for (addr = start; addr < end; ) {
+               uint64_t pt_idx = addr >> RADEON_VM_BLOCK_SIZE;
+               unsigned nptes;
+               uint64_t pte;
+
+               if ((addr & ~mask) == (end & ~mask))
+                       nptes = end - addr;
+               else
+                       nptes = RADEON_VM_PTE_COUNT - (addr & mask);
+
+               pte = radeon_sa_bo_gpu_addr(vm->page_tables[pt_idx]);
+               pte += (addr & mask) * 8;
+
+               if ((last_pte + 8 * count) != pte) {
+
+                       if (count) {
+                               radeon_asic_vm_set_page(rdev, last_pte,
+                                                       last_dst, count,
+                                                       RADEON_GPU_PAGE_SIZE,
+                                                       flags);
+                       }
+
+                       count = nptes;
+                       last_pte = pte;
+                       last_dst = dst;
+               } else {
+                       count += nptes;
+               }
+
+               addr += nptes;
+               dst += nptes * RADEON_GPU_PAGE_SIZE;
+       }
+
+       if (count) {
+               radeon_asic_vm_set_page(rdev, last_pte, last_dst, count,
+                                       RADEON_GPU_PAGE_SIZE, flags);
+       }
+}
+
+/**
  * radeon_vm_bo_update_pte - map a bo into the vm page table
  *
  * @rdev: radeon_device pointer
@@ -887,12 +1084,11 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev,
        struct radeon_semaphore *sem = NULL;
        struct radeon_bo_va *bo_va;
        unsigned nptes, npdes, ndw;
-       uint64_t pe, addr;
-       uint64_t pfn;
+       uint64_t addr;
        int r;
 
        /* nothing to do if vm isn't bound */
-       if (vm->sa_bo == NULL)
+       if (vm->page_directory == NULL)
                return 0;
 
        bo_va = radeon_vm_bo_find(vm, bo);
@@ -939,25 +1135,29 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev,
                }
        }
 
-       /* estimate number of dw needed */
-       /* reserve space for 32-bit padding */
-       ndw = 32;
-
        nptes = radeon_bo_ngpu_pages(bo);
 
-       pfn = (bo_va->soffset / RADEON_GPU_PAGE_SIZE);
+       /* assume two extra pdes in case the mapping overlaps the borders */
+       npdes = (nptes >> RADEON_VM_BLOCK_SIZE) + 2;
 
-       /* handle cases where a bo spans several pdes  */
-       npdes = (ALIGN(pfn + nptes, RADEON_VM_PTE_COUNT) -
-                (pfn & ~(RADEON_VM_PTE_COUNT - 1))) >> RADEON_VM_BLOCK_SIZE;
+       /* estimate number of dw needed */
+       /* semaphore, fence and padding */
+       ndw = 32;
+
+       if (RADEON_VM_BLOCK_SIZE > 11)
+               /* reserve space for one header for every 2k dwords */
+               ndw += (nptes >> 11) * 4;
+       else
+               /* reserve space for one header for
+                   every (1 << BLOCK_SIZE) entries */
+               ndw += (nptes >> RADEON_VM_BLOCK_SIZE) * 4;
 
-       /* reserve space for one header for every 2k dwords */
-       ndw += (nptes >> 11) * 3;
        /* reserve space for pte addresses */
        ndw += nptes * 2;
 
        /* reserve space for one header for every 2k dwords */
-       ndw += (npdes >> 11) * 3;
+       ndw += (npdes >> 11) * 4;
+
        /* reserve space for pde addresses */
        ndw += npdes * 2;
 
@@ -971,22 +1171,14 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev,
                radeon_fence_note_sync(vm->fence, ridx);
        }
 
-       /* update page table entries */
-       pe = vm->pd_gpu_addr;
-       pe += radeon_vm_directory_size(rdev);
-       pe += (bo_va->soffset / RADEON_GPU_PAGE_SIZE) * 8;
-
-       radeon_asic_vm_set_page(rdev, pe, addr, nptes,
-                               RADEON_GPU_PAGE_SIZE, bo_va->flags);
-
-       /* update page directory entries */
-       addr = pe;
-
-       pe = vm->pd_gpu_addr;
-       pe += ((bo_va->soffset / RADEON_GPU_PAGE_SIZE) >> RADEON_VM_BLOCK_SIZE) * 8;
+       r = radeon_vm_update_pdes(rdev, vm, bo_va->soffset, bo_va->eoffset);
+       if (r) {
+               radeon_ring_unlock_undo(rdev, ring);
+               return r;
+       }
 
-       radeon_asic_vm_set_page(rdev, pe, addr, npdes,
-                               RADEON_VM_PTE_COUNT * 8, RADEON_VM_PAGE_VALID);
+       radeon_vm_update_ptes(rdev, vm, bo_va->soffset, bo_va->eoffset,
+                             addr, bo_va->flags);
 
        radeon_fence_unref(&vm->fence);
        r = radeon_fence_emit(rdev, &vm->fence, ridx);
@@ -997,6 +1189,7 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev,
        radeon_ring_unlock_commit(rdev, ring);
        radeon_semaphore_free(rdev, &sem, vm->fence);
        radeon_fence_unref(&vm->last_flush);
+
        return 0;
 }
 
@@ -1056,31 +1249,15 @@ void radeon_vm_bo_invalidate(struct radeon_device *rdev,
  * @rdev: radeon_device pointer
  * @vm: requested vm
  *
- * Init @vm (cayman+).
- * Map the IB pool and any other shared objects into the VM
- * by default as it's used by all VMs.
- * Returns 0 for success, error for failure.
+ * Init @vm fields (cayman+).
  */
-int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm)
+void radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm)
 {
-       struct radeon_bo_va *bo_va;
-       int r;
-
        vm->id = 0;
        vm->fence = NULL;
-       vm->last_pfn = 0;
        mutex_init(&vm->mutex);
        INIT_LIST_HEAD(&vm->list);
        INIT_LIST_HEAD(&vm->va);
-
-       /* map the ib pool buffer at 0 in virtual address space, set
-        * read only
-        */
-       bo_va = radeon_vm_bo_add(rdev, vm, rdev->ring_tmp_bo.bo);
-       r = radeon_vm_bo_set_addr(rdev, bo_va, RADEON_VA_IB_OFFSET,
-                                 RADEON_VM_PAGE_READABLE |
-                                 RADEON_VM_PAGE_SNOOPED);
-       return r;
 }
 
 /**
@@ -1102,17 +1279,6 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm)
        radeon_vm_free_pt(rdev, vm);
        mutex_unlock(&rdev->vm_manager.lock);
 
-       /* remove all bo at this point non are busy any more because unbind
-        * waited for the last vm fence to signal
-        */
-       r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
-       if (!r) {
-               bo_va = radeon_vm_bo_find(vm, rdev->ring_tmp_bo.bo);
-               list_del_init(&bo_va->bo_list);
-               list_del_init(&bo_va->vm_list);
-               radeon_bo_unreserve(rdev->ring_tmp_bo.bo);
-               kfree(bo_va);
-       }
        if (!list_empty(&vm->va)) {
                dev_err(rdev->dev, "still active bo inside vm\n");
        }
index f38fbcc..fe5c1f6 100644 (file)
@@ -53,6 +53,7 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size,
                                struct drm_gem_object **obj)
 {
        struct radeon_bo *robj;
+       unsigned long max_size;
        int r;
 
        *obj = NULL;
@@ -60,11 +61,26 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size,
        if (alignment < PAGE_SIZE) {
                alignment = PAGE_SIZE;
        }
+
+       /* maximun bo size is the minimun btw visible vram and gtt size */
+       max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size);
+       if (size > max_size) {
+               printk(KERN_WARNING "%s:%d alloc size %dMb bigger than %ldMb limit\n",
+                      __func__, __LINE__, size >> 20, max_size >> 20);
+               return -ENOMEM;
+       }
+
+retry:
        r = radeon_bo_create(rdev, size, alignment, kernel, initial_domain, NULL, &robj);
        if (r) {
-               if (r != -ERESTARTSYS)
+               if (r != -ERESTARTSYS) {
+                       if (initial_domain == RADEON_GEM_DOMAIN_VRAM) {
+                               initial_domain |= RADEON_GEM_DOMAIN_GTT;
+                               goto retry;
+                       }
                        DRM_ERROR("Failed to allocate GEM object (%d, %d, %u, %d)\n",
                                  size, initial_domain, alignment, r);
+               }
                return r;
        }
        *obj = &robj->gem_base;
index 83b8d8a..dc781c4 100644 (file)
@@ -419,6 +419,7 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
        /* new gpu have virtual address space support */
        if (rdev->family >= CHIP_CAYMAN) {
                struct radeon_fpriv *fpriv;
+               struct radeon_bo_va *bo_va;
                int r;
 
                fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
@@ -426,7 +427,15 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
                        return -ENOMEM;
                }
 
-               r = radeon_vm_init(rdev, &fpriv->vm);
+               radeon_vm_init(rdev, &fpriv->vm);
+
+               /* map the ib pool buffer read only into
+                * virtual address space */
+               bo_va = radeon_vm_bo_add(rdev, &fpriv->vm,
+                                        rdev->ring_tmp_bo.bo);
+               r = radeon_vm_bo_set_addr(rdev, bo_va, RADEON_VA_IB_OFFSET,
+                                         RADEON_VM_PAGE_READABLE |
+                                         RADEON_VM_PAGE_SNOOPED);
                if (r) {
                        radeon_vm_fini(rdev, &fpriv->vm);
                        kfree(fpriv);
@@ -454,6 +463,17 @@ void radeon_driver_postclose_kms(struct drm_device *dev,
        /* new gpu have virtual address space support */
        if (rdev->family >= CHIP_CAYMAN && file_priv->driver_priv) {
                struct radeon_fpriv *fpriv = file_priv->driver_priv;
+               struct radeon_bo_va *bo_va;
+               int r;
+
+               r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
+               if (!r) {
+                       bo_va = radeon_vm_bo_find(&fpriv->vm,
+                                                 rdev->ring_tmp_bo.bo);
+                       if (bo_va)
+                               radeon_vm_bo_rmv(rdev, bo_va);
+                       radeon_bo_unreserve(rdev->ring_tmp_bo.bo);
+               }
 
                radeon_vm_fini(rdev, &fpriv->vm);
                kfree(fpriv);
index 5677a42..6857cb4 100644 (file)
@@ -295,6 +295,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct drm_device *dev = crtc->dev;
        struct radeon_device *rdev = dev->dev_private;
+       uint32_t crtc_ext_cntl = 0;
        uint32_t mask;
 
        if (radeon_crtc->crtc_id)
@@ -307,6 +308,16 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
                        RADEON_CRTC_VSYNC_DIS |
                        RADEON_CRTC_HSYNC_DIS);
 
+       /*
+        * On all dual CRTC GPUs this bit controls the CRTC of the primary DAC.
+        * Therefore it is set in the DAC DMPS function.
+        * This is different for GPU's with a single CRTC but a primary and a
+        * TV DAC: here it controls the single CRTC no matter where it is
+        * routed. Therefore we set it here.
+        */
+       if (rdev->flags & RADEON_SINGLE_CRTC)
+               crtc_ext_cntl = RADEON_CRTC_CRT_ON;
+       
        switch (mode) {
        case DRM_MODE_DPMS_ON:
                radeon_crtc->enabled = true;
@@ -317,7 +328,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
                else {
                        WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN |
                                                                         RADEON_CRTC_DISP_REQ_EN_B));
-                       WREG32_P(RADEON_CRTC_EXT_CNTL, 0, ~mask);
+                       WREG32_P(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl, ~(mask | crtc_ext_cntl));
                }
                drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
                radeon_crtc_load_lut(crtc);
@@ -331,7 +342,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
                else {
                        WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN |
                                                                                    RADEON_CRTC_DISP_REQ_EN_B));
-                       WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~mask);
+                       WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~(mask | crtc_ext_cntl));
                }
                radeon_crtc->enabled = false;
                /* adjust pm to dpms changes AFTER disabling crtcs */
index 92487e6..f5ba224 100644 (file)
@@ -269,27 +269,6 @@ static const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = {
        .disable = radeon_legacy_encoder_disable,
 };
 
-#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
-
-static uint8_t radeon_legacy_lvds_level(struct backlight_device *bd)
-{
-       struct radeon_backlight_privdata *pdata = bl_get_data(bd);
-       uint8_t level;
-
-       /* Convert brightness to hardware level */
-       if (bd->props.brightness < 0)
-               level = 0;
-       else if (bd->props.brightness > RADEON_MAX_BL_LEVEL)
-               level = RADEON_MAX_BL_LEVEL;
-       else
-               level = bd->props.brightness;
-
-       if (pdata->negative)
-               level = RADEON_MAX_BL_LEVEL - level;
-
-       return level;
-}
-
 u8
 radeon_legacy_get_backlight_level(struct radeon_encoder *radeon_encoder)
 {
@@ -331,6 +310,27 @@ radeon_legacy_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 leve
        radeon_legacy_lvds_update(&radeon_encoder->base, dpms_mode);
 }
 
+#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
+
+static uint8_t radeon_legacy_lvds_level(struct backlight_device *bd)
+{
+       struct radeon_backlight_privdata *pdata = bl_get_data(bd);
+       uint8_t level;
+
+       /* Convert brightness to hardware level */
+       if (bd->props.brightness < 0)
+               level = 0;
+       else if (bd->props.brightness > RADEON_MAX_BL_LEVEL)
+               level = RADEON_MAX_BL_LEVEL;
+       else
+               level = bd->props.brightness;
+
+       if (pdata->negative)
+               level = RADEON_MAX_BL_LEVEL - level;
+
+       return level;
+}
+
 static int radeon_legacy_backlight_update_status(struct backlight_device *bd)
 {
        struct radeon_backlight_privdata *pdata = bl_get_data(bd);
@@ -370,6 +370,7 @@ void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
        struct backlight_properties props;
        struct radeon_backlight_privdata *pdata;
        uint8_t backlight_level;
+       char bl_name[16];
 
        if (!radeon_encoder->enc_priv)
                return;
@@ -389,7 +390,9 @@ void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
        memset(&props, 0, sizeof(props));
        props.max_brightness = RADEON_MAX_BL_LEVEL;
        props.type = BACKLIGHT_RAW;
-       bd = backlight_device_register("radeon_bl", &drm_connector->kdev,
+       snprintf(bl_name, sizeof(bl_name),
+                "radeon_bl%d", dev->primary->index);
+       bd = backlight_device_register(bl_name, &drm_connector->kdev,
                                       pdata, &radeon_backlight_ops, &props);
        if (IS_ERR(bd)) {
                DRM_ERROR("Backlight registration failed\n");
@@ -534,7 +537,9 @@ static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode
                break;
        }
 
-       WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
+       /* handled in radeon_crtc_dpms() */
+       if (!(rdev->flags & RADEON_SINGLE_CRTC))
+               WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
        WREG32(RADEON_DAC_CNTL, dac_cntl);
        WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
 
@@ -659,6 +664,8 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc
 
        if (ASIC_IS_R300(rdev))
                tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
+       else if (ASIC_IS_RV100(rdev))
+               tmp |= (0x1ac << RADEON_DAC_FORCE_DATA_SHIFT);
        else
                tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
 
@@ -668,6 +675,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc
        tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN;
        WREG32(RADEON_DAC_CNTL, tmp);
 
+       tmp = dac_macro_cntl;
        tmp &= ~(RADEON_DAC_PDWN_R |
                 RADEON_DAC_PDWN_G |
                 RADEON_DAC_PDWN_B);
@@ -991,11 +999,7 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder,
 static void radeon_ext_tmds_enc_destroy(struct drm_encoder *encoder)
 {
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv;
-       if (tmds) {
-               if (tmds->i2c_bus)
-                       radeon_i2c_destroy(tmds->i2c_bus);
-       }
+       /* don't destroy the i2c bus record here, this will be done in radeon_i2c_fini */
        kfree(radeon_encoder->enc_priv);
        drm_encoder_cleanup(encoder);
        kfree(radeon_encoder);
@@ -1093,7 +1097,8 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
        } else {
                if (is_tv)
                        WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
-               else
+               /* handled in radeon_crtc_dpms() */
+               else if (!(rdev->flags & RADEON_SINGLE_CRTC))
                        WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
                WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
        }
@@ -1417,13 +1422,104 @@ static bool radeon_legacy_tv_detect(struct drm_encoder *encoder,
        return found;
 }
 
+static bool radeon_legacy_ext_dac_detect(struct drm_encoder *encoder,
+                                        struct drm_connector *connector)
+{
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       uint32_t gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl;
+       uint32_t disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c;
+       uint32_t disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f;
+       uint32_t tmp, crtc2_h_total_disp, crtc2_v_total_disp;
+       uint32_t crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid;
+       bool found = false;
+       int i;
+
+       /* save the regs we need */
+       gpio_monid = RREG32(RADEON_GPIO_MONID);
+       fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
+       disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
+       crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
+       disp_lin_trans_grph_a = RREG32(RADEON_DISP_LIN_TRANS_GRPH_A);
+       disp_lin_trans_grph_b = RREG32(RADEON_DISP_LIN_TRANS_GRPH_B);
+       disp_lin_trans_grph_c = RREG32(RADEON_DISP_LIN_TRANS_GRPH_C);
+       disp_lin_trans_grph_d = RREG32(RADEON_DISP_LIN_TRANS_GRPH_D);
+       disp_lin_trans_grph_e = RREG32(RADEON_DISP_LIN_TRANS_GRPH_E);
+       disp_lin_trans_grph_f = RREG32(RADEON_DISP_LIN_TRANS_GRPH_F);
+       crtc2_h_total_disp = RREG32(RADEON_CRTC2_H_TOTAL_DISP);
+       crtc2_v_total_disp = RREG32(RADEON_CRTC2_V_TOTAL_DISP);
+       crtc2_h_sync_strt_wid = RREG32(RADEON_CRTC2_H_SYNC_STRT_WID);
+       crtc2_v_sync_strt_wid = RREG32(RADEON_CRTC2_V_SYNC_STRT_WID);
+
+       tmp = RREG32(RADEON_GPIO_MONID);
+       tmp &= ~RADEON_GPIO_A_0;
+       WREG32(RADEON_GPIO_MONID, tmp);
+
+       WREG32(RADEON_FP2_GEN_CNTL, (RADEON_FP2_ON |
+                                    RADEON_FP2_PANEL_FORMAT |
+                                    R200_FP2_SOURCE_SEL_TRANS_UNIT |
+                                    RADEON_FP2_DVO_EN |
+                                    R200_FP2_DVO_RATE_SEL_SDR));
+
+       WREG32(RADEON_DISP_OUTPUT_CNTL, (RADEON_DISP_DAC_SOURCE_RMX |
+                                        RADEON_DISP_TRANS_MATRIX_GRAPHICS));
+
+       WREG32(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_EN |
+                                      RADEON_CRTC2_DISP_REQ_EN_B));
+
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0);
+
+       WREG32(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008);
+       WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800);
+       WREG32(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001);
+       WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080);
+
+       for (i = 0; i < 200; i++) {
+               tmp = RREG32(RADEON_GPIO_MONID);
+               if (tmp & RADEON_GPIO_Y_0)
+                       found = true;
+
+               if (found)
+                       break;
+
+               if (!drm_can_sleep())
+                       mdelay(1);
+               else
+                       msleep(1);
+       }
+
+       /* restore the regs we used */
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f);
+       WREG32(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp);
+       WREG32(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp);
+       WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid);
+       WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid);
+       WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+       WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
+       WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
+       WREG32(RADEON_GPIO_MONID, gpio_monid);
+
+       return found;
+}
+
 static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder,
                                                             struct drm_connector *connector)
 {
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
-       uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
-       uint32_t disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp;
+       uint32_t crtc2_gen_cntl = 0, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
+       uint32_t gpiopad_a = 0, pixclks_cntl, tmp;
+       uint32_t disp_output_cntl = 0, disp_hw_debug = 0, crtc_ext_cntl = 0;
        enum drm_connector_status found = connector_status_disconnected;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
@@ -1460,12 +1556,27 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
                return connector_status_disconnected;
        }
 
+       /* R200 uses an external DAC for secondary DAC */
+       if (rdev->family == CHIP_R200) {
+               if (radeon_legacy_ext_dac_detect(encoder, connector))
+                       found = connector_status_connected;
+               return found;
+       }
+
        /* save the regs we need */
        pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
-       gpiopad_a = ASIC_IS_R300(rdev) ? RREG32(RADEON_GPIOPAD_A) : 0;
-       disp_output_cntl = ASIC_IS_R300(rdev) ? RREG32(RADEON_DISP_OUTPUT_CNTL) : 0;
-       disp_hw_debug = ASIC_IS_R300(rdev) ? 0 : RREG32(RADEON_DISP_HW_DEBUG);
-       crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
+
+       if (rdev->flags & RADEON_SINGLE_CRTC) {
+               crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
+       } else {
+               if (ASIC_IS_R300(rdev)) {
+                       gpiopad_a = RREG32(RADEON_GPIOPAD_A);
+                       disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
+               } else {
+                       disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
+               }
+               crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
+       }
        tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
        dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
        dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
@@ -1474,22 +1585,24 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
                               | RADEON_PIX2CLK_DAC_ALWAYS_ONb);
        WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
 
-       if (ASIC_IS_R300(rdev))
-               WREG32_P(RADEON_GPIOPAD_A, 1, ~1);
-
-       tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
-       tmp |= RADEON_CRTC2_CRT2_ON |
-               (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
-
-       WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
-
-       if (ASIC_IS_R300(rdev)) {
-               tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
-               tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
-               WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
+       if (rdev->flags & RADEON_SINGLE_CRTC) {
+               tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON;
+               WREG32(RADEON_CRTC_EXT_CNTL, tmp);
        } else {
-               tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
-               WREG32(RADEON_DISP_HW_DEBUG, tmp);
+               tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
+               tmp |= RADEON_CRTC2_CRT2_ON |
+                       (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
+               WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
+
+               if (ASIC_IS_R300(rdev)) {
+                       WREG32_P(RADEON_GPIOPAD_A, 1, ~1);
+                       tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
+                       tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
+                       WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
+               } else {
+                       tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
+                       WREG32(RADEON_DISP_HW_DEBUG, tmp);
+               }
        }
 
        tmp = RADEON_TV_DAC_NBLANK |
@@ -1531,14 +1644,19 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
        WREG32(RADEON_DAC_CNTL2, dac_cntl2);
        WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
        WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
-       WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
 
-       if (ASIC_IS_R300(rdev)) {
-               WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
-               WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
+       if (rdev->flags & RADEON_SINGLE_CRTC) {
+               WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
        } else {
-               WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
+               WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+               if (ASIC_IS_R300(rdev)) {
+                       WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
+                       WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
+               } else {
+                       WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
+               }
        }
+
        WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
 
        return found;
index 8b27dd6..b91118c 100644 (file)
@@ -105,7 +105,6 @@ int radeon_bo_create(struct radeon_device *rdev,
        struct radeon_bo *bo;
        enum ttm_bo_type type;
        unsigned long page_align = roundup(byte_align, PAGE_SIZE) >> PAGE_SHIFT;
-       unsigned long max_size = 0;
        size_t acc_size;
        int r;
 
@@ -121,18 +120,9 @@ int radeon_bo_create(struct radeon_device *rdev,
        }
        *bo_ptr = NULL;
 
-       /* maximun bo size is the minimun btw visible vram and gtt size */
-       max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size);
-       if ((page_align << PAGE_SHIFT) >= max_size) {
-               printk(KERN_WARNING "%s:%d alloc size %ldM bigger than %ldMb limit\n",
-                       __func__, __LINE__, page_align  >> (20 - PAGE_SHIFT), max_size >> 20);
-               return -ENOMEM;
-       }
-
        acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size,
                                       sizeof(struct radeon_bo));
 
-retry:
        bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL);
        if (bo == NULL)
                return -ENOMEM;
@@ -154,15 +144,6 @@ retry:
                        acc_size, sg, &radeon_ttm_bo_destroy);
        up_read(&rdev->pm.mclk_lock);
        if (unlikely(r != 0)) {
-               if (r != -ERESTARTSYS) {
-                       if (domain == RADEON_GEM_DOMAIN_VRAM) {
-                               domain |= RADEON_GEM_DOMAIN_GTT;
-                               goto retry;
-                       }
-                       dev_err(rdev->dev,
-                               "object_init failed for (%lu, 0x%08X)\n",
-                               size, domain);
-               }
                return r;
        }
        *bo_ptr = bo;
index bba6690..47634f2 100644 (file)
@@ -305,7 +305,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v)
 {
 #if DRM_DEBUG_CODE
        if (ring->count_dw <= 0) {
-               DRM_ERROR("radeon: writting more dword to ring than expected !\n");
+               DRM_ERROR("radeon: writing more dwords to the ring than expected!\n");
        }
 #endif
        ring->ring[ring->wptr++] = v;
index f79633a..4422d63 100644 (file)
@@ -2407,12 +2407,13 @@ static int si_pcie_gart_enable(struct radeon_device *rdev)
        WREG32(0x15DC, 0);
 
        /* empty context1-15 */
-       /* FIXME start with 4G, once using 2 level pt switch to full
-        * vm size space
-        */
        /* set vm size, must be a multiple of 4 */
        WREG32(VM_CONTEXT1_PAGE_TABLE_START_ADDR, 0);
        WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn);
+       /* Assign the pt base to something valid for now; the pts used for
+        * the VMs are determined by the application and setup and assigned
+        * on the fly in the vm part of radeon_gart.c
+        */
        for (i = 1; i < 16; i++) {
                if (i < 8)
                        WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2),
@@ -2473,6 +2474,7 @@ static bool si_vm_reg_valid(u32 reg)
        /* check config regs */
        switch (reg) {
        case GRBM_GFX_INDEX:
+       case CP_STRMOUT_CNTL:
        case VGT_VTX_VECT_EJECT_REG:
        case VGT_CACHE_INVALIDATION:
        case VGT_ESGS_RING_SIZE:
@@ -2807,26 +2809,31 @@ void si_vm_set_page(struct radeon_device *rdev, uint64_t pe,
 {
        struct radeon_ring *ring = &rdev->ring[rdev->asic->vm.pt_ring_index];
        uint32_t r600_flags = cayman_vm_page_flags(rdev, flags);
-       int i;
-       uint64_t value;
 
-       radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 2 + count * 2));
-       radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
-                                WRITE_DATA_DST_SEL(1)));
-       radeon_ring_write(ring, pe);
-       radeon_ring_write(ring, upper_32_bits(pe));
-       for (i = 0; i < count; ++i) {
-               if (flags & RADEON_VM_PAGE_SYSTEM) {
-                       value = radeon_vm_map_gart(rdev, addr);
-                       value &= 0xFFFFFFFFFFFFF000ULL;
-               } else if (flags & RADEON_VM_PAGE_VALID)
-                       value = addr;
-               else
-                       value = 0;
-               addr += incr;
-               value |= r600_flags;
-               radeon_ring_write(ring, value);
-               radeon_ring_write(ring, upper_32_bits(value));
+       while (count) {
+               unsigned ndw = 2 + count * 2;
+               if (ndw > 0x3FFE)
+                       ndw = 0x3FFE;
+
+               radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, ndw));
+               radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
+                                        WRITE_DATA_DST_SEL(1)));
+               radeon_ring_write(ring, pe);
+               radeon_ring_write(ring, upper_32_bits(pe));
+               for (; ndw > 2; ndw -= 2, --count, pe += 8) {
+                       uint64_t value;
+                       if (flags & RADEON_VM_PAGE_SYSTEM) {
+                               value = radeon_vm_map_gart(rdev, addr);
+                               value &= 0xFFFFFFFFFFFFF000ULL;
+                       } else if (flags & RADEON_VM_PAGE_VALID)
+                               value = addr;
+                       else
+                               value = 0;
+                       addr += incr;
+                       value |= r600_flags;
+                       radeon_ring_write(ring, value);
+                       radeon_ring_write(ring, upper_32_bits(value));
+               }
        }
 }
 
@@ -2867,6 +2874,10 @@ void si_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
        radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2);
        radeon_ring_write(ring, 0);
        radeon_ring_write(ring, 1 << vm->id);
+
+       /* sync PFP to ME, otherwise we might get invalid PFP reads */
+       radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0));
+       radeon_ring_write(ring, 0x0);
 }
 
 /*
index 7d2a20e..a8871af 100644 (file)
 #       define RDERR_INT_ENABLE                         (1 << 0)
 #       define GUI_IDLE_INT_ENABLE                      (1 << 19)
 
+#define        CP_STRMOUT_CNTL                                 0x84FC
 #define        SCRATCH_REG0                                    0x8500
 #define        SCRATCH_REG1                                    0x8504
 #define        SCRATCH_REG2                                    0x8508
index c71d493..1c350fc 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 402ab69..bf6e4b5 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 860dc48..bd2a3b4 100644 (file)
@@ -749,7 +749,10 @@ static int ttm_get_pages(struct page **pages, unsigned npages, int flags,
        /* clear the pages coming from the pool if requested */
        if (flags & TTM_PAGE_FLAG_ZERO_ALLOC) {
                list_for_each_entry(p, &plist, lru) {
-                       clear_page(page_address(p));
+                       if (PageHighMem(p))
+                               clear_highpage(p);
+                       else
+                               clear_page(page_address(p));
                }
        }
 
index bf82601..7d759a4 100644 (file)
@@ -308,9 +308,7 @@ int ttm_tt_swapin(struct ttm_tt *ttm)
                if (unlikely(to_page == NULL))
                        goto out_err;
 
-               preempt_disable();
                copy_highpage(to_page, from_page);
-               preempt_enable();
                page_cache_release(from_page);
        }
 
@@ -358,9 +356,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
                        ret = PTR_ERR(to_page);
                        goto out_err;
                }
-               preempt_disable();
                copy_highpage(to_page, from_page);
-               preempt_enable();
                set_page_dirty(to_page);
                mark_page_accessed(to_page);
                page_cache_release(to_page);
index fccd361..87aa5f5 100644 (file)
@@ -104,7 +104,7 @@ udl_fb_user_fb_create(struct drm_device *dev,
 
 int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,
                     const char *front, char **urb_buf_ptr,
-                    u32 byte_offset, u32 byte_width,
+                    u32 byte_offset, u32 device_byte_offset, u32 byte_width,
                     int *ident_ptr, int *sent_ptr);
 
 int udl_dumb_create(struct drm_file *file_priv,
index 69a2b16..d4ab3be 100644 (file)
@@ -114,9 +114,10 @@ static void udlfb_dpy_deferred_io(struct fb_info *info,
        list_for_each_entry(cur, &fbdefio->pagelist, lru) {
 
                if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8),
-                                 &urb, (char *) info->fix.smem_start,
-                                 &cmd, cur->index << PAGE_SHIFT,
-                                 PAGE_SIZE, &bytes_identical, &bytes_sent))
+                                    &urb, (char *) info->fix.smem_start,
+                                    &cmd, cur->index << PAGE_SHIFT,
+                                    cur->index << PAGE_SHIFT,
+                                    PAGE_SIZE, &bytes_identical, &bytes_sent))
                        goto error;
                bytes_rendered += PAGE_SIZE;
        }
@@ -187,10 +188,11 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
        for (i = y; i < y + height ; i++) {
                const int line_offset = fb->base.pitches[0] * i;
                const int byte_offset = line_offset + (x * bpp);
-
+               const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp);
                if (udl_render_hline(dev, bpp, &urb,
                                     (char *) fb->obj->vmapping,
-                                    &cmd, byte_offset, width * bpp,
+                                    &cmd, byte_offset, dev_byte_offset,
+                                    width * bpp,
                                     &bytes_identical, &bytes_sent))
                        goto error;
        }
index dc09552..142fee5 100644 (file)
@@ -213,11 +213,12 @@ static void udl_compress_hline16(
  */
 int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,
                     const char *front, char **urb_buf_ptr,
-                    u32 byte_offset, u32 byte_width,
+                    u32 byte_offset, u32 device_byte_offset,
+                    u32 byte_width,
                     int *ident_ptr, int *sent_ptr)
 {
        const u8 *line_start, *line_end, *next_pixel;
-       u32 base16 = 0 + (byte_offset / bpp) * 2;
+       u32 base16 = 0 + (device_byte_offset / bpp) * 2;
        struct urb *urb = *urb_ptr;
        u8 *cmd = *urb_buf_ptr;
        u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length;
index 3ce68a2..d1498bf 100644 (file)
@@ -306,7 +306,7 @@ void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin)
 
        BUG_ON(!atomic_read(&bo->reserved));
        BUG_ON(old_mem_type != TTM_PL_VRAM &&
-              old_mem_type != VMW_PL_FLAG_GMR);
+              old_mem_type != VMW_PL_GMR);
 
        pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED;
        if (pin)
index ed3c1e7..2dd185e 100644 (file)
@@ -1098,6 +1098,11 @@ static void vmw_pm_complete(struct device *kdev)
        struct drm_device *dev = pci_get_drvdata(pdev);
        struct vmw_private *dev_priv = vmw_priv(dev);
 
+       mutex_lock(&dev_priv->hw_mutex);
+       vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2);
+       (void) vmw_read(dev_priv, SVGA_REG_ID);
+       mutex_unlock(&dev_priv->hw_mutex);
+
        /**
         * Reclaim 3d reference held by fbdev and potentially
         * start fifo.
index b07ca2e..7290811 100644 (file)
@@ -110,6 +110,8 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
        memcpy_fromio(bounce, &fifo_mem[SVGA_FIFO_3D_CAPS], size);
 
        ret = copy_to_user(buffer, bounce, size);
+       if (ret)
+               ret = -EFAULT;
        vfree(bounce);
 
        if (unlikely(ret != 0))
index 06ebdbb..fd7722a 100644 (file)
@@ -522,6 +522,12 @@ static const struct hid_device_id apple_devices[] = {
                .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),
                .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI),
+               .driver_data = APPLE_HAS_FN },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO),
+               .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS),
+               .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
                .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
index bd3971b..f4109fd 100644 (file)
@@ -1532,6 +1532,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
@@ -2139,6 +2142,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
        { }
index 269b509..9d7a428 100644 (file)
 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI  0x0252
 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO   0x0253
 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS   0x0254
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI  0x0259
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO   0x025a
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS   0x025b
 #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI  0x0249
 #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO   0x024a
 #define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS   0x024b
index 3acdcfc..6fcd466 100644 (file)
 #define MS_RDESC               0x08
 #define MS_NOGET               0x10
 #define MS_DUPLICATE_USAGES    0x20
+#define MS_RDESC_3K            0x40
 
-/*
- * Microsoft Wireless Desktop Receiver (Model 1028) has
- * 'Usage Min/Max' where it ought to have 'Physical Min/Max'
- */
 static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                unsigned int *rsize)
 {
        unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
 
+       /*
+        * Microsoft Wireless Desktop Receiver (Model 1028) has
+        * 'Usage Min/Max' where it ought to have 'Physical Min/Max'
+        */
        if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 &&
                        rdesc[559] == 0x29) {
                hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n");
                rdesc[557] = 0x35;
                rdesc[559] = 0x45;
        }
+       /* the same as above (s/usage/physical/) */
+       if ((quirks & MS_RDESC_3K) && *rsize == 106 && rdesc[94] == 0x19 &&
+                       rdesc[95] == 0x00 && rdesc[96] == 0x29 &&
+                       rdesc[97] == 0xff) {
+               rdesc[94] = 0x35;
+               rdesc[96] = 0x45;
+       }
        return rdesc;
 }
 
@@ -192,7 +200,7 @@ static const struct hid_device_id ms_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB),
                .driver_data = MS_PRESENTER },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K),
-               .driver_data = MS_ERGONOMY },
+               .driver_data = MS_ERGONOMY | MS_RDESC_3K },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0),
                .driver_data = MS_NOGET },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500),
index 3eb02b9..7867d69 100644 (file)
@@ -210,8 +210,7 @@ static struct mt_class mt_classes[] = {
        },
        { .name = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
                .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
-                       MT_QUIRK_SLOT_IS_CONTACTNUMBER,
-               .maxcontacts = 10
+                       MT_QUIRK_SLOT_IS_CONTACTNUMBER
        },
 
        { .name = MT_CLS_FLATFROG,
@@ -421,11 +420,11 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                         * contact max are global to the report */
                        td->last_field_index = field->index;
                        return -1;
-               }
                case HID_DG_TOUCH:
                        /* Legacy devices use TIPSWITCH and not TOUCH.
                         * Let's just ignore this field. */
                        return -1;
+               }
                /* let hid-input decide for the others */
                return 0;
 
index 17d15bb..7c47fc3 100644 (file)
@@ -42,7 +42,6 @@ static struct cdev hidraw_cdev;
 static struct class *hidraw_class;
 static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES];
 static DEFINE_MUTEX(minors_lock);
-static void drop_ref(struct hidraw *hid, int exists_bit);
 
 static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
@@ -114,7 +113,7 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer,
        __u8 *buf;
        int ret = 0;
 
-       if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
+       if (!hidraw_table[minor]) {
                ret = -ENODEV;
                goto out;
        }
@@ -262,7 +261,7 @@ static int hidraw_open(struct inode *inode, struct file *file)
        }
 
        mutex_lock(&minors_lock);
-       if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
+       if (!hidraw_table[minor]) {
                err = -ENODEV;
                goto out_unlock;
        }
@@ -299,12 +298,36 @@ out:
 static int hidraw_release(struct inode * inode, struct file * file)
 {
        unsigned int minor = iminor(inode);
+       struct hidraw *dev;
        struct hidraw_list *list = file->private_data;
+       int ret;
+       int i;
+
+       mutex_lock(&minors_lock);
+       if (!hidraw_table[minor]) {
+               ret = -ENODEV;
+               goto unlock;
+       }
 
-       drop_ref(hidraw_table[minor], 0);
        list_del(&list->node);
+       dev = hidraw_table[minor];
+       if (!--dev->open) {
+               if (list->hidraw->exist) {
+                       hid_hw_power(dev->hid, PM_HINT_NORMAL);
+                       hid_hw_close(dev->hid);
+               } else {
+                       kfree(list->hidraw);
+               }
+       }
+
+       for (i = 0; i < HIDRAW_BUFFER_SIZE; ++i)
+               kfree(list->buffer[i].value);
        kfree(list);
-       return 0;
+       ret = 0;
+unlock:
+       mutex_unlock(&minors_lock);
+
+       return ret;
 }
 
 static long hidraw_ioctl(struct file *file, unsigned int cmd,
@@ -506,7 +529,21 @@ EXPORT_SYMBOL_GPL(hidraw_connect);
 void hidraw_disconnect(struct hid_device *hid)
 {
        struct hidraw *hidraw = hid->hidraw;
-       drop_ref(hidraw, 1);
+
+       mutex_lock(&minors_lock);
+       hidraw->exist = 0;
+
+       device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
+
+       hidraw_table[hidraw->minor] = NULL;
+
+       if (hidraw->open) {
+               hid_hw_close(hid);
+               wake_up_interruptible(&hidraw->wait);
+       } else {
+               kfree(hidraw);
+       }
+       mutex_unlock(&minors_lock);
 }
 EXPORT_SYMBOL_GPL(hidraw_disconnect);
 
@@ -555,23 +592,3 @@ void hidraw_exit(void)
        unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES);
 
 }
-
-static void drop_ref(struct hidraw *hidraw, int exists_bit)
-{
-       mutex_lock(&minors_lock);
-       if (exists_bit) {
-               hid_hw_close(hidraw->hid);
-               hidraw->exist = 0;
-               if (hidraw->open)
-                       wake_up_interruptible(&hidraw->wait);
-       } else {
-               --hidraw->open;
-       }
-
-       if (!hidraw->open && !hidraw->exist) {
-               device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
-               hidraw_table[hidraw->minor] = NULL;
-               kfree(hidraw);
-       }
-       mutex_unlock(&minors_lock);
-}
index 4065374..f4c3d28 100644 (file)
@@ -146,14 +146,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 +168,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 +177,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 +193,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 +208,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 +227,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 c4633de..4800d4c 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 8d5fcb5..a930f09 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 1f9e8af..409b5c1 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 a227be4..520e5bf 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 984a3f1..24426a7 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 b8d01c5..1970494 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..9465c05
--- /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_ADCIN3,
+       [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 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 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 = 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 68ad7d2..34ab2a8 100644 (file)
@@ -2,7 +2,7 @@
  * fam15h_power.c - AMD Family 15h processor power monitoring
  *
  * Copyright (c) 2011 Advanced Micro Devices, Inc.
- * Author: Andreas Herrmann <andreas.herrmann3@amd.com>
+ * Author: Andreas Herrmann <herrmann.der.user@googlemail.com>
  *
  *
  * This driver is free software; you can redistribute it and/or
 #include <asm/processor.h>
 
 MODULE_DESCRIPTION("AMD Family 15h CPU processor power monitor");
-MODULE_AUTHOR("Andreas Herrmann <andreas.herrmann3@amd.com>");
+MODULE_AUTHOR("Andreas Herrmann <herrmann.der.user@googlemail.com>");
 MODULE_LICENSE("GPL");
 
+/* Family 16h Northbridge's function 4 PCI ID */
+#define PCI_DEVICE_ID_AMD_16H_NB_F4    0x1534
+
 /* D18F3 */
 #define REG_NORTHBRIDGE_CAP            0xe8
 
@@ -248,6 +251,7 @@ static void __devexit fam15h_power_remove(struct pci_dev *pdev)
 
 static DEFINE_PCI_DEVICE_TABLE(fam15h_power_id_table) = {
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },
+       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) },
        {}
 };
 MODULE_DEVICE_TABLE(pci, fam15h_power_id_table);
index 36509ae..1381a2e 100644 (file)
@@ -630,7 +630,9 @@ static struct platform_driver gpio_fan_driver = {
        .driver = {
                .name   = "gpio-fan",
                .pm     = GPIO_FAN_PM,
+#ifdef CONFIG_OF_GPIO
                .of_match_table = of_match_ptr(of_gpio_fan_match),
+#endif
        },
 };
 
index 2b72634..8e7158c 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 2ca6a5a..60745a5 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 1821b74..de3c7e0 100644 (file)
@@ -2083,6 +2083,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
        mutex_init(&data->lock);
        mutex_init(&data->update_lock);
        data->name = w83627ehf_device_names[sio_data->kind];
+       data->bank = 0xff;              /* Force initial bank selection */
        platform_set_drvdata(pdev, data);
 
        /* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */
index 5b1a6a6..af15899 100644 (file)
@@ -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)
index 5a5046d..20f11d3 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 39ab7bc..ed397c6 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 0536452..301942d 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 f0e8286..79710bc 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 beee6b2..1722f50 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 65dd599..e9df461 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 2d33d62..395b516 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 aa59a25..c02bf20 100644 (file)
@@ -39,6 +39,7 @@
 #define        AT91_TWI_STOP           0x0002  /* Send a Stop Condition */
 #define        AT91_TWI_MSEN           0x0004  /* Master Transfer Enable */
 #define        AT91_TWI_SVDIS          0x0020  /* Slave Transfer Disable */
+#define        AT91_TWI_QUICK          0x0040  /* SMBus quick command */
 #define        AT91_TWI_SWRST          0x0080  /* Software Reset */
 
 #define        AT91_TWI_MMR            0x0004  /* Master Mode Register */
@@ -212,7 +213,11 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
 
        INIT_COMPLETION(dev->cmd_complete);
        dev->transfer_status = 0;
-       if (dev->msg->flags & I2C_M_RD) {
+
+       if (!dev->buf_len) {
+               at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_QUICK);
+               at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP);
+       } else if (dev->msg->flags & I2C_M_RD) {
                unsigned start_flags = AT91_TWI_START;
 
                if (at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_RXRDY) {
index 3779315..6abc00d 100644 (file)
@@ -82,7 +82,8 @@
 #include <linux/wait.h>
 #include <linux/err.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 +193,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 +923,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 +1062,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];
index 1f58197..0670da7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Freescale MXS I2C bus driver
  *
- * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K.
+ * Copyright (C) 2011-2012 Wolfram Sang, Pengutronix e.K.
  *
  * based on a (non-working) driver which was:
  *
 
 #define DRIVER_NAME "mxs-i2c"
 
-static bool use_pioqueue;
-module_param(use_pioqueue, bool, 0);
-MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA");
-
 #define MXS_I2C_CTRL0          (0x00)
 #define MXS_I2C_CTRL0_SET      (0x04)
 
@@ -75,23 +71,6 @@ MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA");
                                 MXS_I2C_CTRL1_SLAVE_STOP_IRQ | \
                                 MXS_I2C_CTRL1_SLAVE_IRQ)
 
-#define MXS_I2C_QUEUECTRL      (0x60)
-#define MXS_I2C_QUEUECTRL_SET  (0x64)
-#define MXS_I2C_QUEUECTRL_CLR  (0x68)
-
-#define MXS_I2C_QUEUECTRL_QUEUE_RUN            0x20
-#define MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE       0x04
-
-#define MXS_I2C_QUEUESTAT      (0x70)
-#define MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY        0x00002000
-#define MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK 0x0000001F
-
-#define MXS_I2C_QUEUECMD       (0x80)
-
-#define MXS_I2C_QUEUEDATA      (0x90)
-
-#define MXS_I2C_DATA           (0xa0)
-
 
 #define MXS_CMD_I2C_SELECT     (MXS_I2C_CTRL0_RETAIN_CLOCK |   \
                                 MXS_I2C_CTRL0_PRE_SEND_START | \
@@ -153,7 +132,6 @@ struct mxs_i2c_dev {
        const struct mxs_i2c_speed_config *speed;
 
        /* DMA support components */
-       bool                            dma_mode;
        int                             dma_channel;
        struct dma_chan                 *dmach;
        struct mxs_dma_data             dma_data;
@@ -172,99 +150,6 @@ static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
        writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2);
 
        writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
-       if (i2c->dma_mode)
-               writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
-                       i2c->regs + MXS_I2C_QUEUECTRL_CLR);
-       else
-               writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
-                       i2c->regs + MXS_I2C_QUEUECTRL_SET);
-}
-
-static void mxs_i2c_pioq_setup_read(struct mxs_i2c_dev *i2c, u8 addr, int len,
-                                       int flags)
-{
-       u32 data;
-
-       writel(MXS_CMD_I2C_SELECT, i2c->regs + MXS_I2C_QUEUECMD);
-
-       data = (addr << 1) | I2C_SMBUS_READ;
-       writel(data, i2c->regs + MXS_I2C_DATA);
-
-       data = MXS_CMD_I2C_READ | MXS_I2C_CTRL0_XFER_COUNT(len) | flags;
-       writel(data, i2c->regs + MXS_I2C_QUEUECMD);
-}
-
-static void mxs_i2c_pioq_setup_write(struct mxs_i2c_dev *i2c,
-                                   u8 addr, u8 *buf, int len, int flags)
-{
-       u32 data;
-       int i, shifts_left;
-
-       data = MXS_CMD_I2C_WRITE | MXS_I2C_CTRL0_XFER_COUNT(len + 1) | flags;
-       writel(data, i2c->regs + MXS_I2C_QUEUECMD);
-
-       /*
-        * We have to copy the slave address (u8) and buffer (arbitrary number
-        * of u8) into the data register (u32). To achieve that, the u8 are put
-        * into the MSBs of 'data' which is then shifted for the next u8. When
-        * appropriate, 'data' is written to MXS_I2C_DATA. So, the first u32
-        * looks like this:
-        *
-        *  3          2          1          0
-        * 10987654|32109876|54321098|76543210
-        * --------+--------+--------+--------
-        * buffer+2|buffer+1|buffer+0|slave_addr
-        */
-
-       data = ((addr << 1) | I2C_SMBUS_WRITE) << 24;
-
-       for (i = 0; i < len; i++) {
-               data >>= 8;
-               data |= buf[i] << 24;
-               if ((i & 3) == 2)
-                       writel(data, i2c->regs + MXS_I2C_DATA);
-       }
-
-       /* Write out the remaining bytes if any */
-       shifts_left = 24 - (i & 3) * 8;
-       if (shifts_left)
-               writel(data >> shifts_left, i2c->regs + MXS_I2C_DATA);
-}
-
-/*
- * TODO: should be replaceable with a waitqueue and RD_QUEUE_IRQ (setting the
- * rd_threshold to 1). Couldn't get this to work, though.
- */
-static int mxs_i2c_wait_for_data(struct mxs_i2c_dev *i2c)
-{
-       unsigned long timeout = jiffies + msecs_to_jiffies(1000);
-
-       while (readl(i2c->regs + MXS_I2C_QUEUESTAT)
-                       & MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY) {
-                       if (time_after(jiffies, timeout))
-                               return -ETIMEDOUT;
-                       cond_resched();
-       }
-
-       return 0;
-}
-
-static int mxs_i2c_finish_read(struct mxs_i2c_dev *i2c, u8 *buf, int len)
-{
-       u32 uninitialized_var(data);
-       int i;
-
-       for (i = 0; i < len; i++) {
-               if ((i & 3) == 0) {
-                       if (mxs_i2c_wait_for_data(i2c))
-                               return -ETIMEDOUT;
-                       data = readl(i2c->regs + MXS_I2C_QUEUEDATA);
-               }
-               buf[i] = data & 0xff;
-               data >>= 8;
-       }
-
-       return 0;
 }
 
 static void mxs_i2c_dma_finish(struct mxs_i2c_dev *i2c)
@@ -402,12 +287,14 @@ read_init_dma_fail:
 select_init_dma_fail:
        dma_unmap_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE);
 select_init_pio_fail:
+       dmaengine_terminate_all(i2c->dmach);
        return -EINVAL;
 
 /* Write failpath. */
 write_init_dma_fail:
        dma_unmap_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
 write_init_pio_fail:
+       dmaengine_terminate_all(i2c->dmach);
        return -EINVAL;
 }
 
@@ -432,39 +319,17 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
        init_completion(&i2c->cmd_complete);
        i2c->cmd_err = 0;
 
-       if (i2c->dma_mode) {
-               ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
-               if (ret)
-                       return ret;
-       } else {
-               if (msg->flags & I2C_M_RD) {
-                       mxs_i2c_pioq_setup_read(i2c, msg->addr,
-                                               msg->len, flags);
-               } else {
-                       mxs_i2c_pioq_setup_write(i2c, msg->addr, msg->buf,
-                                               msg->len, flags);
-               }
-
-               writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
-                       i2c->regs + MXS_I2C_QUEUECTRL_SET);
-       }
+       ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
+       if (ret)
+               return ret;
 
        ret = wait_for_completion_timeout(&i2c->cmd_complete,
                                                msecs_to_jiffies(1000));
        if (ret == 0)
                goto timeout;
 
-       if (!i2c->dma_mode && !i2c->cmd_err && (msg->flags & I2C_M_RD)) {
-               ret = mxs_i2c_finish_read(i2c, msg->buf, msg->len);
-               if (ret)
-                       goto timeout;
-       }
-
        if (i2c->cmd_err == -ENXIO)
                mxs_i2c_reset(i2c);
-       else
-               writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
-                               i2c->regs + MXS_I2C_QUEUECTRL_CLR);
 
        dev_dbg(i2c->dev, "Done with err=%d\n", i2c->cmd_err);
 
@@ -472,8 +337,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
 
 timeout:
        dev_dbg(i2c->dev, "Timeout!\n");
-       if (i2c->dma_mode)
-               mxs_i2c_dma_finish(i2c);
+       mxs_i2c_dma_finish(i2c);
        mxs_i2c_reset(i2c);
        return -ETIMEDOUT;
 }
@@ -502,7 +366,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
 {
        struct mxs_i2c_dev *i2c = dev_id;
        u32 stat = readl(i2c->regs + MXS_I2C_CTRL1) & MXS_I2C_IRQ_MASK;
-       bool is_last_cmd;
 
        if (!stat)
                return IRQ_NONE;
@@ -515,14 +378,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
                /* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */
                i2c->cmd_err = -EIO;
 
-       if (!i2c->dma_mode) {
-               is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) &
-                       MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0;
-
-               if (is_last_cmd || i2c->cmd_err)
-                       complete(&i2c->cmd_complete);
-       }
-
        writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR);
 
        return IRQ_HANDLED;
@@ -556,23 +411,14 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
        int ret;
 
        /*
-        * The MXS I2C DMA mode is prefered and enabled by default.
-        * The PIO mode is still supported, but should be used only
-        * for debuging purposes etc.
-        */
-       i2c->dma_mode = !use_pioqueue;
-       if (!i2c->dma_mode)
-               dev_info(dev, "Using PIOQUEUE mode for I2C transfers!\n");
-
-       /*
         * TODO: This is a temporary solution and should be changed
         * to use generic DMA binding later when the helpers get in.
         */
        ret = of_property_read_u32(node, "fsl,i2c-dma-channel",
                                   &i2c->dma_channel);
        if (ret) {
-               dev_warn(dev, "Failed to get DMA channel, using PIOQUEUE!\n");
-               i2c->dma_mode = 0;
+               dev_err(dev, "Failed to get DMA channel!\n");
+               return -ENODEV;
        }
 
        ret = of_property_read_u32(node, "clock-frequency", &speed);
@@ -634,15 +480,13 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
        }
 
        /* Setup the DMA */
-       if (i2c->dma_mode) {
-               dma_cap_zero(mask);
-               dma_cap_set(DMA_SLAVE, mask);
-               i2c->dma_data.chan_irq = dmairq;
-               i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c);
-               if (!i2c->dmach) {
-                       dev_err(dev, "Failed to request dma\n");
-                       return -ENODEV;
-               }
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
+       i2c->dma_data.chan_irq = dmairq;
+       i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c);
+       if (!i2c->dmach) {
+               dev_err(dev, "Failed to request dma\n");
+               return -ENODEV;
        }
 
        platform_set_drvdata(pdev, i2c);
index 698d7ac..02c3115 100644 (file)
@@ -644,7 +644,11 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
 
        pm_runtime_get_sync(&dev->adev->dev);
 
-       clk_enable(dev->clk);
+       status = clk_prepare_enable(dev->clk);
+       if (status) {
+               dev_err(&dev->adev->dev, "can't prepare_enable clock\n");
+               goto out_clk;
+       }
 
        status = init_hw(dev);
        if (status)
@@ -671,7 +675,8 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
        }
 
 out:
-       clk_disable(dev->clk);
+       clk_disable_unprepare(dev->clk);
+out_clk:
        pm_runtime_put_sync(&dev->adev->dev);
 
        dev->busy = false;
index bffd550..15da1ac 100644 (file)
@@ -9,10 +9,6 @@
  * kind, whether express or implied.
  */
 
-/*
- * This driver can be used from the device tree, see
- *     Documentation/devicetree/bindings/i2c/ocore-i2c.txt
- */
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
index db31eae..3525c9e 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/slab.h>
 #include <linux/i2c-omap.h>
 #include <linux/pm_runtime.h>
-#include <linux/pm_qos.h>
 
 /* I2C controller revisions */
 #define OMAP_I2C_OMAP1_REV_2           0x20
@@ -187,8 +186,9 @@ struct omap_i2c_dev {
        int                     reg_shift;      /* bit shift for I2C register addresses */
        struct completion       cmd_complete;
        struct resource         *ioarea;
-       u32                     latency;        /* maximum MPU wkup latency */
-       struct pm_qos_request   pm_qos_request;
+       u32                     latency;        /* maximum mpu wkup latency */
+       void                    (*set_mpu_wkup_lat)(struct device *dev,
+                                                   long latency);
        u32                     speed;          /* Speed of bus in kHz */
        u32                     dtrev;          /* extra revision from DT */
        u32                     flags;
@@ -494,7 +494,9 @@ static void omap_i2c_resize_fifo(struct omap_i2c_dev *dev, u8 size, bool is_rx)
                dev->b_hw = 1; /* Enable hardware fixes */
 
        /* calculate wakeup latency constraint for MPU */
-       dev->latency = (1000000 * dev->threshold) / (1000 * dev->speed / 8);
+       if (dev->set_mpu_wkup_lat != NULL)
+               dev->latency = (1000000 * dev->threshold) /
+                       (1000 * dev->speed / 8);
 }
 
 /*
@@ -522,6 +524,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
        dev->buf = msg->buf;
        dev->buf_len = msg->len;
 
+       /* make sure writes to dev->buf_len are ordered */
+       barrier();
+
        omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len);
 
        /* Clear the FIFO Buffers */
@@ -579,7 +584,6 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
         */
        timeout = wait_for_completion_timeout(&dev->cmd_complete,
                                                OMAP_I2C_TIMEOUT);
-       dev->buf_len = 0;
        if (timeout == 0) {
                dev_err(dev->dev, "controller timed out\n");
                omap_i2c_init(dev);
@@ -629,16 +633,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
        if (r < 0)
                goto out;
 
-       /*
-        * When waiting for completion of a i2c transfer, we need to
-        * set a wake up latency constraint for the MPU. This is to
-        * ensure quick enough wakeup from idle, when transfer
-        * completes.
-        */
-       if (dev->latency)
-               pm_qos_add_request(&dev->pm_qos_request,
-                                  PM_QOS_CPU_DMA_LATENCY,
-                                  dev->latency);
+       if (dev->set_mpu_wkup_lat != NULL)
+               dev->set_mpu_wkup_lat(dev->dev, dev->latency);
 
        for (i = 0; i < num; i++) {
                r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1)));
@@ -646,8 +642,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
                        break;
        }
 
-       if (dev->latency)
-               pm_qos_remove_request(&dev->pm_qos_request);
+       if (dev->set_mpu_wkup_lat != NULL)
+               dev->set_mpu_wkup_lat(dev->dev, -1);
 
        if (r == 0)
                r = num;
@@ -1104,6 +1100,7 @@ omap_i2c_probe(struct platform_device *pdev)
        } else if (pdata != NULL) {
                dev->speed = pdata->clkrate;
                dev->flags = pdata->flags;
+               dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat;
                dev->dtrev = pdata->rev;
        }
 
@@ -1159,8 +1156,9 @@ omap_i2c_probe(struct platform_device *pdev)
                        dev->b_hw = 1; /* Enable hardware fixes */
 
                /* calculate wakeup latency constraint for MPU */
-               dev->latency = (1000000 * dev->fifo_size) /
-                              (1000 * dev->speed / 8);
+               if (dev->set_mpu_wkup_lat != NULL)
+                       dev->latency = (1000000 * dev->fifo_size) /
+                                      (1000 * dev->speed / 8);
        }
 
        /* reset ASAP, clearing any IRQs */
index 3e0335f..9d90272 100644 (file)
@@ -806,6 +806,7 @@ static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c)
                        dev_err(i2c->dev, "invalid gpio[%d]: %d\n", idx, gpio);
                        goto free_gpio;
                }
+               i2c->gpios[idx] = gpio;
 
                ret = gpio_request(gpio, "i2c-bus");
                if (ret) {
index f981ac4..dcea77b 100644 (file)
@@ -742,7 +742,7 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
        }
 
        ret = devm_request_irq(&pdev->dev, i2c_dev->irq,
-                       tegra_i2c_isr, 0, pdev->name, i2c_dev);
+                       tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev);
        if (ret) {
                dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);
                return ret;
index a7edf98..e388590 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/irqflags.h>
 #include <linux/rwsem.h>
 #include <linux/pm_runtime.h>
+#include <linux/acpi.h>
 #include <asm/uaccess.h>
 
 #include "i2c-core.h"
@@ -78,6 +79,10 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv)
        if (of_driver_match_device(dev, drv))
                return 1;
 
+       /* Then ACPI style match */
+       if (acpi_driver_match_device(dev, drv))
+               return 1;
+
        driver = to_i2c_driver(drv);
        /* match on an id table if there is one */
        if (driver->id_table)
@@ -539,6 +544,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
        client->dev.bus = &i2c_bus_type;
        client->dev.type = &i2c_client_type;
        client->dev.of_node = info->of_node;
+       ACPI_HANDLE_SET(&client->dev, info->acpi_node.handle);
 
        /* For 10-bit clients, add an arbitrary offset to avoid collisions */
        dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
similarity index 75%
rename from drivers/i2c/busses/i2c-stub.c
rename to drivers/i2c/i2c-stub.c
index b1b3447..d0a9c59 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;
        }
 
@@ -219,4 +218,3 @@ MODULE_LICENSE("GPL");
 
 module_init(i2c_stub_init);
 module_exit(i2c_stub_exit);
-
index 5f097f3..7fa5b24 100644 (file)
@@ -169,7 +169,7 @@ static int __devinit i2c_mux_pinctrl_probe(struct platform_device *pdev)
        mux->busses = devm_kzalloc(&pdev->dev,
                                   sizeof(mux->busses) * mux->pdata->bus_count,
                                   GFP_KERNEL);
-       if (!mux->states) {
+       if (!mux->busses) {
                dev_err(&pdev->dev, "Cannot allocate busses\n");
                ret = -ENOMEM;
                goto err;
index b0f6b4c..c49c04d 100644 (file)
@@ -56,7 +56,6 @@
 #include <linux/kernel.h>
 #include <linux/cpuidle.h>
 #include <linux/clockchips.h>
-#include <linux/hrtimer.h>     /* ktime_get_real() */
 #include <trace/events/power.h>
 #include <linux/sched.h>
 #include <linux/notifier.h>
@@ -72,6 +71,7 @@
 static struct cpuidle_driver intel_idle_driver = {
        .name = "intel_idle",
        .owner = THIS_MODULE,
+       .en_core_tk_irqen = 1,
 };
 /* intel_idle.max_cstate=0 disables driver */
 static int max_cstate = MWAIT_MAX_NUM_CSTATES - 1;
@@ -281,8 +281,6 @@ static int intel_idle(struct cpuidle_device *dev,
        struct cpuidle_state_usage *state_usage = &dev->states_usage[index];
        unsigned long eax = (unsigned long)cpuidle_get_statedata(state_usage);
        unsigned int cstate;
-       ktime_t kt_before, kt_after;
-       s64 usec_delta;
        int cpu = smp_processor_id();
 
        cstate = (((eax) >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) + 1;
@@ -297,8 +295,6 @@ static int intel_idle(struct cpuidle_device *dev,
        if (!(lapic_timer_reliable_states & (1 << (cstate))))
                clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
 
-       kt_before = ktime_get_real();
-
        stop_critical_timings();
        if (!need_resched()) {
 
@@ -310,17 +306,9 @@ static int intel_idle(struct cpuidle_device *dev,
 
        start_critical_timings();
 
-       kt_after = ktime_get_real();
-       usec_delta = ktime_to_us(ktime_sub(kt_after, kt_before));
-
-       local_irq_enable();
-
        if (!(lapic_timer_reliable_states & (1 << (cstate))))
                clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
 
-       /* Update cpuidle counters */
-       dev->last_residency = (int)usec_delta;
-
        return index;
 }
 
index 6e3f143..fc937ac 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 f7fa3c0..761f2b6 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 57e07c6..afd8179 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 d2fb38d..2f215b9 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 21a7941..0a903c1 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 3c3b54c..25b2cdf 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 6ae2ac4..f0f8928 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 c0ec7d4..1abbc17 100644 (file)
@@ -26,10 +26,14 @@ static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src)
  * input_mt_init_slots() - initialize MT input slots
  * @dev: input device supporting MT events and finger tracking
  * @num_slots: number of slots used by the device
+ * @flags: mt tasks to handle in core
  *
  * This function allocates all necessary memory for MT slot handling
  * in the input device, prepares the ABS_MT_SLOT and
  * ABS_MT_TRACKING_ID events for use and sets up appropriate buffers.
+ * Depending on the flags set, it also performs pointer emulation and
+ * frame synchronization.
+ *
  * May be called repeatedly. Returns -EINVAL if attempting to
  * reinitialize with a different number of slots.
  */
index b62b589..f362883 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 b4b65af..de08740 100644 (file)
@@ -335,6 +335,7 @@ config KEYBOARD_LOCOMO
 config KEYBOARD_LPC32XX
        tristate "LPC32XX matrix key scanner support"
        depends on ARCH_LPC32XX && OF
+       select INPUT_MATRIXKMAP
        help
          Say Y here if you want to use NXP LPC32XX SoC key scanner interface,
          connected to a key matrix.
index 803ff6f..cad9d5d 100644 (file)
@@ -368,6 +368,9 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)
        unsigned int mask = 0, direct_key_num = 0;
        unsigned long kpc = 0;
 
+       /* clear pending interrupt bit */
+       keypad_readl(KPC);
+
        /* enable matrix keys with automatic scan */
        if (pdata->matrix_key_rows && pdata->matrix_key_cols) {
                kpc |= KPC_ASACT | KPC_MIE | KPC_ME | KPC_MS_ALL;
index 443ad64..d88d9be 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/input.h>
 #include <linux/of.h>
 #include <linux/export.h>
+#include <linux/module.h>
 #include <linux/input/matrix_keypad.h>
 
 static bool matrix_keypad_map_key(struct input_dev *input_dev,
@@ -161,3 +162,5 @@ int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data,
        return 0;
 }
 EXPORT_SYMBOL(matrix_keypad_build_keymap);
+
+MODULE_LICENSE("GPL");
index 02ca868..6f7d990 100644 (file)
@@ -311,7 +311,6 @@ static void xenkbd_backend_changed(struct xenbus_device *dev,
        case XenbusStateReconfiguring:
        case XenbusStateReconfigured:
        case XenbusStateUnknown:
-       case XenbusStateClosed:
                break;
 
        case XenbusStateInitWait:
@@ -350,6 +349,10 @@ InitWait:
 
                break;
 
+       case XenbusStateClosed:
+               if (dev->state == XenbusStateClosed)
+                       break;
+               /* Missed the backend's CLOSING state -- fallthrough */
        case XenbusStateClosing:
                xenbus_frontend_closed(dev);
                break;
index 3a78f23..2baff1b 100644 (file)
 #define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI   0x0262
 #define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO    0x0263
 #define USB_DEVICE_ID_APPLE_WELLSPRING7_JIS    0x0264
+/* MacbookPro10,2 (unibody, October 2012) */
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI  0x0259
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO   0x025a
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS   0x025b
 
 #define BCM5974_DEVICE(prod) {                                 \
        .match_flags = (USB_DEVICE_ID_MATCH_DEVICE |            \
@@ -137,6 +141,10 @@ static const struct usb_device_id bcm5974_table[] = {
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI),
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ISO),
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),
+       /* MacbookPro10,2 */
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI),
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO),
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS),
        /* Terminating entry */
        {}
 };
@@ -379,6 +387,19 @@ static const struct bcm5974_config bcm5974_config_table[] = {
                { SN_COORD, -150, 6730 },
                { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
        },
+       {
+               USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI,
+               USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO,
+               USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS,
+               HAS_INTEGRATED_BUTTON,
+               0x84, sizeof(struct bt_data),
+               0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+               { SN_PRESSURE, 0, 300 },
+               { SN_WIDTH, 0, 2048 },
+               { SN_COORD, -4750, 5280 },
+               { SN_COORD, -150, 6730 },
+               { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
+       },
        {}
 };
 
index a1b4c37..4c842c3 100644 (file)
@@ -12,8 +12,8 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #define MOUSEDEV_MINOR_BASE    32
-#define MOUSEDEV_MINORS                32
-#define MOUSEDEV_MIX           31
+#define MOUSEDEV_MINORS                31
+#define MOUSEDEV_MIX           63
 
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -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 9edf980..858ad44 100644 (file)
@@ -391,7 +391,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
                                                        features->pktlen = WACOM_PKGLEN_TPC2FG;
                                                }
 
-                                               if (features->type == MTSCREEN)
+                                               if (features->type == MTSCREEN || features->type == WACOM_24HDT)
                                                        features->pktlen = WACOM_PKGLEN_MTOUCH;
 
                                                if (features->type == BAMBOO_PT) {
@@ -402,6 +402,14 @@ static int wacom_parse_hid(struct usb_interface *intf,
                                                        features->x_max =
                                                                get_unaligned_le16(&report[i + 8]);
                                                        i += 15;
+                                               } else if (features->type == WACOM_24HDT) {
+                                                       features->x_max =
+                                                               get_unaligned_le16(&report[i + 3]);
+                                                       features->x_phy =
+                                                               get_unaligned_le16(&report[i + 8]);
+                                                       features->unit = report[i - 1];
+                                                       features->unitExpo = report[i - 3];
+                                                       i += 12;
                                                } else {
                                                        features->x_max =
                                                                get_unaligned_le16(&report[i + 3]);
@@ -434,6 +442,12 @@ static int wacom_parse_hid(struct usb_interface *intf,
                                                        features->y_phy =
                                                                get_unaligned_le16(&report[i + 6]);
                                                        i += 7;
+                                               } else if (type == WACOM_24HDT) {
+                                                       features->y_max =
+                                                               get_unaligned_le16(&report[i + 3]);
+                                                       features->y_phy =
+                                                               get_unaligned_le16(&report[i - 2]);
+                                                       i += 7;
                                                } else if (type == BAMBOO_PT) {
                                                        features->y_phy =
                                                                get_unaligned_le16(&report[i + 3]);
@@ -541,6 +555,9 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
                        /* MT Tablet PC touch */
                        return wacom_set_device_mode(intf, 3, 4, 4);
                }
+               else if (features->type == WACOM_24HDT) {
+                       return wacom_set_device_mode(intf, 18, 3, 2);
+               }
        } else if (features->device_type == BTN_TOOL_PEN) {
                if (features->type <= BAMBOO_PT && features->type != WIRELESS) {
                        return wacom_set_device_mode(intf, 2, 2, 2);
@@ -613,6 +630,30 @@ struct wacom_usbdev_data {
 static LIST_HEAD(wacom_udev_list);
 static DEFINE_MUTEX(wacom_udev_list_lock);
 
+static struct usb_device *wacom_get_sibling(struct usb_device *dev, int vendor, int product)
+{
+       int port1;
+       struct usb_device *sibling;
+
+       if (vendor == 0 && product == 0)
+               return dev;
+
+       if (dev->parent == NULL)
+               return NULL;
+
+       usb_hub_for_each_child(dev->parent, port1, sibling) {
+               struct usb_device_descriptor *d;
+               if (sibling == NULL)
+                       continue;
+
+               d = &sibling->descriptor;
+               if (d->idVendor == vendor && d->idProduct == product)
+                       return sibling;
+       }
+
+       return NULL;
+}
+
 static struct wacom_usbdev_data *wacom_get_usbdev_data(struct usb_device *dev)
 {
        struct wacom_usbdev_data *data;
@@ -1257,13 +1298,19 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
        strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name));
 
        if (features->quirks & WACOM_QUIRK_MULTI_INPUT) {
+               struct usb_device *other_dev;
+
                /* Append the device type to the name */
                strlcat(wacom_wac->name,
                        features->device_type == BTN_TOOL_PEN ?
                                " Pen" : " Finger",
                        sizeof(wacom_wac->name));
 
-               error = wacom_add_shared_data(wacom_wac, dev);
+
+               other_dev = wacom_get_sibling(dev, features->oVid, features->oPid);
+               if (other_dev == NULL || wacom_get_usbdev_data(other_dev) == NULL)
+                       other_dev = dev;
+               error = wacom_add_shared_data(wacom_wac, other_dev);
                if (error)
                        goto fail3;
        }
index c3468c8..0a67031 100644 (file)
@@ -806,6 +806,70 @@ static int find_slot_from_contactid(struct wacom_wac *wacom, int contactid)
        return -1;
 }
 
+static int int_dist(int x1, int y1, int x2, int y2)
+{
+       int x = x2 - x1;
+       int y = y2 - y1;
+
+       return int_sqrt(x*x + y*y);
+}
+
+static int wacom_24hdt_irq(struct wacom_wac *wacom)
+{
+       struct input_dev *input = wacom->input;
+       char *data = wacom->data;
+       int i;
+       int current_num_contacts = data[61];
+       int contacts_to_send = 0;
+
+       /*
+        * First packet resets the counter since only the first
+        * packet in series will have non-zero current_num_contacts.
+        */
+       if (current_num_contacts)
+               wacom->num_contacts_left = current_num_contacts;
+
+       /* There are at most 4 contacts per packet */
+       contacts_to_send = min(4, wacom->num_contacts_left);
+
+       for (i = 0; i < contacts_to_send; i++) {
+               int offset = (WACOM_BYTES_PER_24HDT_PACKET * i) + 1;
+               bool touch = data[offset] & 0x1 && !wacom->shared->stylus_in_proximity;
+               int id = data[offset + 1];
+               int slot = find_slot_from_contactid(wacom, id);
+
+               if (slot < 0)
+                       continue;
+               input_mt_slot(input, slot);
+               input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
+
+               if (touch) {
+                       int t_x = le16_to_cpup((__le16 *)&data[offset + 2]);
+                       int c_x = le16_to_cpup((__le16 *)&data[offset + 4]);
+                       int t_y = le16_to_cpup((__le16 *)&data[offset + 6]);
+                       int c_y = le16_to_cpup((__le16 *)&data[offset + 8]);
+                       int w = le16_to_cpup((__le16 *)&data[offset + 10]);
+                       int h = le16_to_cpup((__le16 *)&data[offset + 12]);
+
+                       input_report_abs(input, ABS_MT_POSITION_X, t_x);
+                       input_report_abs(input, ABS_MT_POSITION_Y, t_y);
+                       input_report_abs(input, ABS_MT_TOUCH_MAJOR, min(w,h));
+                       input_report_abs(input, ABS_MT_WIDTH_MAJOR, min(w, h) + int_dist(t_x, t_y, c_x, c_y));
+                       input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h));
+                       input_report_abs(input, ABS_MT_ORIENTATION, w > h);
+               }
+               wacom->slots[slot] = touch ? id : -1;
+       }
+
+       input_mt_report_pointer_emulation(input, true);
+
+       wacom->num_contacts_left -= contacts_to_send;
+       if (wacom->num_contacts_left <= 0)
+               wacom->num_contacts_left = 0;
+
+       return 1;
+}
+
 static int wacom_mt_touch(struct wacom_wac *wacom)
 {
        struct input_dev *input = wacom->input;
@@ -1255,6 +1319,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
                sync = wacom_intuos_irq(wacom_wac);
                break;
 
+       case WACOM_24HDT:
+               sync = wacom_24hdt_irq(wacom_wac);
+               break;
+
        case INTUOS5S:
        case INTUOS5:
        case INTUOS5L:
@@ -1340,7 +1408,8 @@ void wacom_setup_device_quirks(struct wacom_features *features)
 
        /* these device have multiple inputs */
        if (features->type >= WIRELESS ||
-           (features->type >= INTUOS5S && features->type <= INTUOS5L))
+           (features->type >= INTUOS5S && features->type <= INTUOS5L) ||
+           (features->oVid && features->oPid))
                features->quirks |= WACOM_QUIRK_MULTI_INPUT;
 
        /* quirk for bamboo touch with 2 low res touches */
@@ -1449,6 +1518,9 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
 
                input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
                input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0);
+
+               __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
                wacom_setup_cintiq(wacom_wac);
                break;
 
@@ -1575,6 +1647,15 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
                __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
                break;
 
+       case WACOM_24HDT:
+               if (features->device_type == BTN_TOOL_FINGER) {
+                       input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0);
+                       input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, features->x_max, 0, 0);
+                       input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR, 0, features->y_max, 0, 0);
+                       input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0);
+               }
+               /* fall through */
+
        case MTSCREEN:
                if (features->device_type == BTN_TOOL_FINGER) {
                        wacom_wac->slots = kmalloc(features->touch_max *
@@ -1869,8 +1950,11 @@ static const struct wacom_features wacom_features_0xF4 =
        { "Wacom Cintiq 24HD",       WACOM_PKGLEN_INTUOS,   104480, 65600, 2047,
          63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0xF8 =
-       { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS,   104480, 65600, 2047,
-         63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+       { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS,   104480, 65600, 2047, /* Pen */
+         63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 };
+static const struct wacom_features wacom_features_0xF6 =
+       { "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */
+         .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10 };
 static const struct wacom_features wacom_features_0x3F =
        { "Wacom Cintiq 21UX",    WACOM_PKGLEN_INTUOS,    87200, 65600, 1023,
          63, CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
@@ -2113,6 +2197,7 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0x47) },
        { USB_DEVICE_WACOM(0xF4) },
        { USB_DEVICE_WACOM(0xF8) },
+       { USB_DEVICE_WACOM(0xF6) },
        { USB_DEVICE_WACOM(0xFA) },
        { USB_DEVICE_LENOVO(0x6004) },
        { }
index 96c185c..345f1e7 100644 (file)
@@ -29,6 +29,7 @@
 
 /* wacom data size per MT contact */
 #define WACOM_BYTES_PER_MT_PACKET      11
+#define WACOM_BYTES_PER_24HDT_PACKET   14
 
 /* device IDs */
 #define STYLUS_DEVICE_ID       0x02
@@ -49,6 +50,7 @@
 #define WACOM_REPORT_TPCHID            15
 #define WACOM_REPORT_TPCST             16
 #define WACOM_REPORT_TPC1FGE           18
+#define WACOM_REPORT_24HDT             1
 
 /* device quirks */
 #define WACOM_QUIRK_MULTI_INPUT                0x0001
@@ -81,6 +83,7 @@ enum {
        WACOM_MO,
        WIRELESS,
        BAMBOO_PT,
+       WACOM_24HDT,
        TABLETPC,   /* add new TPC below */
        TABLETPCE,
        TABLETPC2FG,
@@ -109,6 +112,8 @@ struct wacom_features {
        int distance_fuzz;
        unsigned quirks;
        unsigned touch_max;
+       int oVid;
+       int oPid;
 };
 
 struct wacom_shared {
index 1ba232c..f7668b2 100644 (file)
@@ -239,7 +239,7 @@ config TOUCHSCREEN_EETI
 
 config TOUCHSCREEN_EGALAX
        tristate "EETI eGalax multi-touch panel support"
-       depends on I2C
+       depends on I2C && OF
        help
          Say Y here to enable support for I2C connected EETI
          eGalax multi-touch panels.
index f02028e..78e5d9a 100644 (file)
@@ -955,7 +955,8 @@ static int ads7846_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume);
 
-static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads7846 *ts)
+static int __devinit ads7846_setup_pendown(struct spi_device *spi,
+                                          struct ads7846 *ts)
 {
        struct ads7846_platform_data *pdata = spi->dev.platform_data;
        int err;
@@ -981,6 +982,9 @@ static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads784
 
                ts->gpio_pendown = pdata->gpio_pendown;
 
+               if (pdata->gpio_pendown_debounce)
+                       gpio_set_debounce(pdata->gpio_pendown,
+                                         pdata->gpio_pendown_debounce);
        } else {
                dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n");
                return -EINVAL;
index c1e3460..13fa62f 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/bitops.h>
 #include <linux/input/mt.h>
+#include <linux/of_gpio.h>
 
 /*
  * Mouse Mode: some panel may configure the controller to mouse mode,
@@ -122,9 +123,17 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id)
 /* wake up controller by an falling edge of interrupt gpio.  */
 static int egalax_wake_up_device(struct i2c_client *client)
 {
-       int gpio = irq_to_gpio(client->irq);
+       struct device_node *np = client->dev.of_node;
+       int gpio;
        int ret;
 
+       if (!np)
+               return -ENODEV;
+
+       gpio = of_get_named_gpio(np, "wakeup-gpios", 0);
+       if (!gpio_is_valid(gpio))
+               return -ENODEV;
+
        ret = gpio_request(gpio, "egalax_irq");
        if (ret < 0) {
                dev_err(&client->dev,
@@ -181,7 +190,11 @@ static int __devinit egalax_ts_probe(struct i2c_client *client,
        ts->input_dev = input_dev;
 
        /* controller may be in sleep, wake it up. */
-       egalax_wake_up_device(client);
+       error = egalax_wake_up_device(client);
+       if (error) {
+               dev_err(&client->dev, "Failed to wake up the controller\n");
+               goto err_free_dev;
+       }
 
        ret = egalax_firmware_version(client);
        if (ret < 0) {
@@ -274,11 +287,17 @@ static int egalax_ts_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(egalax_ts_pm_ops, egalax_ts_suspend, egalax_ts_resume);
 
+static struct of_device_id egalax_ts_dt_ids[] = {
+       { .compatible = "eeti,egalax_ts" },
+       { /* sentinel */ }
+};
+
 static struct i2c_driver egalax_ts_driver = {
        .driver = {
                .name   = "egalax_ts",
                .owner  = THIS_MODULE,
                .pm     = &egalax_ts_pm_ops,
+               .of_match_table = of_match_ptr(egalax_ts_dt_ids),
        },
        .id_table       = egalax_ts_id,
        .probe          = egalax_ts_probe,
index 63209aa..eb96f16 100644 (file)
@@ -107,7 +107,6 @@ static int tsc_connect(struct serio *serio, struct serio_driver *drv)
        __set_bit(BTN_TOUCH, input_dev->keybit);
        input_set_abs_params(ptsc->dev, ABS_X, 0, 0x3ff, 0, 0);
        input_set_abs_params(ptsc->dev, ABS_Y, 0, 0x3ff, 0, 0);
-       input_set_abs_params(ptsc->dev, ABS_PRESSURE, 0, 0, 0, 0);
 
        serio_set_drvdata(serio, ptsc);
 
index 18b0d99..81837b0 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 d4a4cd4..0badfa4 100644 (file)
@@ -4108,7 +4108,7 @@ static void swap_pci_ref(struct pci_dev **from, struct pci_dev *to)
 static int intel_iommu_add_device(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
-       struct pci_dev *bridge, *dma_pdev;
+       struct pci_dev *bridge, *dma_pdev = NULL;
        struct iommu_group *group;
        int ret;
 
@@ -4122,7 +4122,7 @@ static int intel_iommu_add_device(struct device *dev)
                        dma_pdev = pci_get_domain_bus_and_slot(
                                                pci_domain_nr(pdev->bus),
                                                bridge->subordinate->number, 0);
-               else
+               if (!dma_pdev)
                        dma_pdev = pci_dev_get(bridge);
        } else
                dma_pdev = pci_dev_get(pdev);
index 0b4d62e..c0f7a42 100644 (file)
@@ -200,7 +200,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)
@@ -1054,6 +1054,7 @@ static int smmu_debugfs_stats_show(struct seq_file *s, void *v)
                        stats[i], val, offs);
        }
        seq_printf(s, "\n");
+       dput(dent);
 
        return 0;
 }
index dc670cc..16c78f1 100644 (file)
@@ -168,7 +168,8 @@ static int __init armctrl_of_init(struct device_node *node,
 }
 
 static struct of_device_id irq_of_match[] __initconst = {
-       { .compatible = "brcm,bcm2835-armctrl-ic", .data = armctrl_of_init }
+       { .compatible = "brcm,bcm2835-armctrl-ic", .data = armctrl_of_init },
+       { }
 };
 
 void __init bcm2835_init_irq(void)
index a233ed5..86cd75a 100644 (file)
@@ -4,7 +4,7 @@
 
 menuconfig ISDN
        bool "ISDN support"
-       depends on NET
+       depends on NET && NETDEVICES
        depends on !S390 && !UML
        ---help---
          ISDN ("Integrated Services Digital Network", called RNIS in France)
index 5275887..c44950d 100644 (file)
@@ -617,7 +617,13 @@ static void int_in_work(struct work_struct *work)
        if (rc == 0)
                /* success, resubmit interrupt read URB */
                rc = usb_submit_urb(urb, GFP_ATOMIC);
-       if (rc != 0 && rc != -ENODEV) {
+
+       switch (rc) {
+       case 0:         /* success */
+       case -ENODEV:   /* device gone */
+       case -EINVAL:   /* URB already resubmitted, or terminal badness */
+               break;
+       default:        /* failure: try to recover by resetting the device */
                dev_err(cs->dev, "clear halt failed: %s\n", get_usb_rcmsg(rc));
                rc = usb_lock_device_for_reset(ucs->udev, ucs->interface);
                if (rc == 0) {
@@ -2442,7 +2448,9 @@ static void gigaset_disconnect(struct usb_interface *interface)
 }
 
 /* gigaset_suspend
- * This function is called before the USB connection is suspended.
+ * This function is called before the USB connection is suspended
+ * or before the USB device is reset.
+ * In the latter case, message == PMSG_ON.
  */
 static int gigaset_suspend(struct usb_interface *intf, pm_message_t message)
 {
@@ -2498,7 +2506,12 @@ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message)
        del_timer_sync(&ucs->timer_atrdy);
        del_timer_sync(&ucs->timer_cmd_in);
        del_timer_sync(&ucs->timer_int_in);
-       cancel_work_sync(&ucs->int_in_wq);
+
+       /* don't try to cancel int_in_wq from within reset as it
+        * might be the one requesting the reset
+        */
+       if (message.event != PM_EVENT_ON)
+               cancel_work_sync(&ucs->int_in_wq);
 
        gig_dbg(DEBUG_SUSPEND, "suspend complete");
        return 0;
index 2302fbe..9c6650e 100644 (file)
@@ -6,7 +6,7 @@ if ISDN_I4L
 
 config ISDN_PPP
        bool "Support synchronous PPP"
-       depends on INET && NETDEVICES
+       depends on INET
        select SLHC
        help
          Over digital connections such as ISDN, there is no need to
index 8c610fa..e2a945e 100644 (file)
@@ -1312,7 +1312,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)
                        } else
                                return -EINVAL;
                        break;
-#ifdef CONFIG_NETDEVICES
                case IIOCNETGPN:
                        /* Get peer phone number of a connected
                         * isdn network interface */
@@ -1322,7 +1321,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)
                                return isdn_net_getpeer(&phone, argp);
                        } else
                                return -EINVAL;
-#endif
                default:
                        return -EINVAL;
                }
@@ -1352,7 +1350,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)
                case IIOCNETLCR:
                        printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n");
                        return -ENODEV;
-#ifdef CONFIG_NETDEVICES
                case IIOCNETAIF:
                        /* Add a network-interface */
                        if (arg) {
@@ -1491,7 +1488,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)
                                return -EFAULT;
                        return isdn_net_force_hangup(name);
                        break;
-#endif                          /* CONFIG_NETDEVICES */
                case IIOCSETVER:
                        dev->net_verbose = arg;
                        printk(KERN_INFO "isdn: Verbose-Level is %d\n", dev->net_verbose);
index b312056..4239b39 100644 (file)
@@ -33,8 +33,6 @@
 struct led_trigger_cpu {
        char name[MAX_NAME_LEN];
        struct led_trigger *_trig;
-       struct mutex lock;
-       int lock_is_inited;
 };
 
 static DEFINE_PER_CPU(struct led_trigger_cpu, cpu_trig);
@@ -50,12 +48,6 @@ void ledtrig_cpu(enum cpu_led_event ledevt)
 {
        struct led_trigger_cpu *trig = &__get_cpu_var(cpu_trig);
 
-       /* mutex lock should be initialized before calling mutex_call() */
-       if (!trig->lock_is_inited)
-               return;
-
-       mutex_lock(&trig->lock);
-
        /* Locate the correct CPU LED */
        switch (ledevt) {
        case CPU_LED_IDLE_END:
@@ -75,8 +67,6 @@ void ledtrig_cpu(enum cpu_led_event ledevt)
                /* Will leave the LED as it is */
                break;
        }
-
-       mutex_unlock(&trig->lock);
 }
 EXPORT_SYMBOL(ledtrig_cpu);
 
@@ -117,14 +107,9 @@ static int __init ledtrig_cpu_init(void)
        for_each_possible_cpu(cpu) {
                struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu);
 
-               mutex_init(&trig->lock);
-
                snprintf(trig->name, MAX_NAME_LEN, "cpu%d", cpu);
 
-               mutex_lock(&trig->lock);
                led_trigger_register_simple(trig->name, &trig->_trig);
-               trig->lock_is_inited = 1;
-               mutex_unlock(&trig->lock);
        }
 
        register_syscore_ops(&ledtrig_cpu_syscore_ops);
@@ -142,15 +127,9 @@ static void __exit ledtrig_cpu_exit(void)
        for_each_possible_cpu(cpu) {
                struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu);
 
-               mutex_lock(&trig->lock);
-
                led_trigger_unregister_simple(trig->_trig);
                trig->_trig = NULL;
                memset(trig->name, 0, MAX_NAME_LEN);
-               trig->lock_is_inited = 0;
-
-               mutex_unlock(&trig->lock);
-               mutex_destroy(&trig->lock);
        }
 
        unregister_syscore_ops(&ledtrig_cpu_syscore_ops);
index 02db918..77e6eff 100644 (file)
@@ -740,8 +740,14 @@ static void rq_completed(struct mapped_device *md, int rw, int run_queue)
        if (!md_in_flight(md))
                wake_up(&md->wait);
 
+       /*
+        * Run this off this callpath, as drivers could invoke end_io while
+        * inside their request_fn (and holding the queue lock). Calling
+        * back into ->request_fn() could deadlock attempting to grab the
+        * queue lock again.
+        */
        if (run_queue)
-               blk_run_queue(md->queue);
+               blk_run_queue_async(md->queue);
 
        /*
         * dm_put() must be at the end of this function. See the comment above
index 45135f6..5e7dc77 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 9ab768a..6120071 100644 (file)
@@ -1817,10 +1817,10 @@ retry:
                        memset(bbp, 0xff, PAGE_SIZE);
 
                        for (i = 0 ; i < bb->count ; i++) {
-                               u64 internal_bb = *p++;
+                               u64 internal_bb = p[i];
                                u64 store_bb = ((BB_OFFSET(internal_bb) << 10)
                                                | BB_LEN(internal_bb));
-                               *bbp++ = cpu_to_le64(store_bb);
+                               bbp[i] = cpu_to_le64(store_bb);
                        }
                        bb->changed = 0;
                        if (read_seqretry(&bb->lock, seq))
@@ -5294,7 +5294,7 @@ void md_stop_writes(struct mddev *mddev)
 }
 EXPORT_SYMBOL_GPL(md_stop_writes);
 
-void md_stop(struct mddev *mddev)
+static void __md_stop(struct mddev *mddev)
 {
        mddev->ready = 0;
        mddev->pers->stop(mddev);
@@ -5304,6 +5304,18 @@ void md_stop(struct mddev *mddev)
        mddev->pers = NULL;
        clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
 }
+
+void md_stop(struct mddev *mddev)
+{
+       /* stop the array and free an attached data structures.
+        * This is called from dm-raid
+        */
+       __md_stop(mddev);
+       bitmap_destroy(mddev);
+       if (mddev->bio_set)
+               bioset_free(mddev->bio_set);
+}
+
 EXPORT_SYMBOL_GPL(md_stop);
 
 static int md_set_readonly(struct mddev *mddev, struct block_device *bdev)
@@ -5364,7 +5376,7 @@ static int do_md_stop(struct mddev * mddev, int mode,
                        set_disk_ro(disk, 0);
 
                __md_stop_writes(mddev);
-               md_stop(mddev);
+               __md_stop(mddev);
                mddev->queue->merge_bvec_fn = NULL;
                mddev->queue->backing_dev_info.congested_fn = NULL;
 
@@ -7936,9 +7948,9 @@ int md_is_badblock(struct badblocks *bb, sector_t s, int sectors,
                   sector_t *first_bad, int *bad_sectors)
 {
        int hi;
-       int lo = 0;
+       int lo;
        u64 *p = bb->page;
-       int rv = 0;
+       int rv;
        sector_t target = s + sectors;
        unsigned seq;
 
@@ -7953,7 +7965,8 @@ int md_is_badblock(struct badblocks *bb, sector_t s, int sectors,
 
 retry:
        seq = read_seqbegin(&bb->lock);
-
+       lo = 0;
+       rv = 0;
        hi = bb->count;
 
        /* Binary search between lo and hi for 'target'
index 8034fbd..a0f7309 100644 (file)
@@ -963,7 +963,7 @@ static void raid1_unplug(struct blk_plug_cb *cb, bool from_schedule)
        struct r1conf *conf = mddev->private;
        struct bio *bio;
 
-       if (from_schedule) {
+       if (from_schedule || current->bio_list) {
                spin_lock_irq(&conf->device_lock);
                bio_list_merge(&conf->pending_bio_list, &plug->pending);
                conf->pending_count += plug->pending_cnt;
@@ -2710,7 +2710,7 @@ static struct r1conf *setup_conf(struct mddev *mddev)
                    || disk_idx < 0)
                        continue;
                if (test_bit(Replacement, &rdev->flags))
-                       disk = conf->mirrors + conf->raid_disks + disk_idx;
+                       disk = conf->mirrors + mddev->raid_disks + disk_idx;
                else
                        disk = conf->mirrors + disk_idx;
 
index 906ccbd..c9acbd7 100644 (file)
@@ -499,7 +499,7 @@ static void raid10_end_write_request(struct bio *bio, int error)
         */
        one_write_done(r10_bio);
        if (dec_rdev)
-               rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev);
+               rdev_dec_pending(rdev, conf->mddev);
 }
 
 /*
@@ -1069,7 +1069,7 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule)
        struct r10conf *conf = mddev->private;
        struct bio *bio;
 
-       if (from_schedule) {
+       if (from_schedule || current->bio_list) {
                spin_lock_irq(&conf->device_lock);
                bio_list_merge(&conf->pending_bio_list, &plug->pending);
                conf->pending_count += plug->pending_cnt;
@@ -1334,18 +1334,21 @@ retry_write:
                        blocked_rdev = rrdev;
                        break;
                }
+               if (rdev && (test_bit(Faulty, &rdev->flags)
+                            || test_bit(Unmerged, &rdev->flags)))
+                       rdev = NULL;
                if (rrdev && (test_bit(Faulty, &rrdev->flags)
                              || test_bit(Unmerged, &rrdev->flags)))
                        rrdev = NULL;
 
                r10_bio->devs[i].bio = NULL;
                r10_bio->devs[i].repl_bio = NULL;
-               if (!rdev || test_bit(Faulty, &rdev->flags) ||
-                   test_bit(Unmerged, &rdev->flags)) {
+
+               if (!rdev && !rrdev) {
                        set_bit(R10BIO_Degraded, &r10_bio->state);
                        continue;
                }
-               if (test_bit(WriteErrorSeen, &rdev->flags)) {
+               if (rdev && test_bit(WriteErrorSeen, &rdev->flags)) {
                        sector_t first_bad;
                        sector_t dev_sector = r10_bio->devs[i].addr;
                        int bad_sectors;
@@ -1387,8 +1390,10 @@ retry_write:
                                        max_sectors = good_sectors;
                        }
                }
-               r10_bio->devs[i].bio = bio;
-               atomic_inc(&rdev->nr_pending);
+               if (rdev) {
+                       r10_bio->devs[i].bio = bio;
+                       atomic_inc(&rdev->nr_pending);
+               }
                if (rrdev) {
                        r10_bio->devs[i].repl_bio = bio;
                        atomic_inc(&rrdev->nr_pending);
@@ -1444,69 +1449,71 @@ retry_write:
        for (i = 0; i < conf->copies; i++) {
                struct bio *mbio;
                int d = r10_bio->devs[i].devnum;
-               if (!r10_bio->devs[i].bio)
-                       continue;
+               if (r10_bio->devs[i].bio) {
+                       struct md_rdev *rdev = conf->mirrors[d].rdev;
+                       mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
+                       md_trim_bio(mbio, r10_bio->sector - bio->bi_sector,
+                                   max_sectors);
+                       r10_bio->devs[i].bio = mbio;
+
+                       mbio->bi_sector = (r10_bio->devs[i].addr+
+                                          choose_data_offset(r10_bio,
+                                                             rdev));
+                       mbio->bi_bdev = rdev->bdev;
+                       mbio->bi_end_io = raid10_end_write_request;
+                       mbio->bi_rw = WRITE | do_sync | do_fua | do_discard;
+                       mbio->bi_private = r10_bio;
 
-               mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
-               md_trim_bio(mbio, r10_bio->sector - bio->bi_sector,
-                           max_sectors);
-               r10_bio->devs[i].bio = mbio;
+                       atomic_inc(&r10_bio->remaining);
 
-               mbio->bi_sector = (r10_bio->devs[i].addr+
-                                  choose_data_offset(r10_bio,
-                                                     conf->mirrors[d].rdev));
-               mbio->bi_bdev = conf->mirrors[d].rdev->bdev;
-               mbio->bi_end_io = raid10_end_write_request;
-               mbio->bi_rw = WRITE | do_sync | do_fua | do_discard;
-               mbio->bi_private = r10_bio;
+                       cb = blk_check_plugged(raid10_unplug, mddev,
+                                              sizeof(*plug));
+                       if (cb)
+                               plug = container_of(cb, struct raid10_plug_cb,
+                                                   cb);
+                       else
+                               plug = NULL;
+                       spin_lock_irqsave(&conf->device_lock, flags);
+                       if (plug) {
+                               bio_list_add(&plug->pending, mbio);
+                               plug->pending_cnt++;
+                       } else {
+                               bio_list_add(&conf->pending_bio_list, mbio);
+                               conf->pending_count++;
+                       }
+                       spin_unlock_irqrestore(&conf->device_lock, flags);
+                       if (!plug)
+                               md_wakeup_thread(mddev->thread);
+               }
 
-               atomic_inc(&r10_bio->remaining);
+               if (r10_bio->devs[i].repl_bio) {
+                       struct md_rdev *rdev = conf->mirrors[d].replacement;
+                       if (rdev == NULL) {
+                               /* Replacement just got moved to main 'rdev' */
+                               smp_mb();
+                               rdev = conf->mirrors[d].rdev;
+                       }
+                       mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
+                       md_trim_bio(mbio, r10_bio->sector - bio->bi_sector,
+                                   max_sectors);
+                       r10_bio->devs[i].repl_bio = mbio;
+
+                       mbio->bi_sector = (r10_bio->devs[i].addr +
+                                          choose_data_offset(
+                                                  r10_bio, rdev));
+                       mbio->bi_bdev = rdev->bdev;
+                       mbio->bi_end_io = raid10_end_write_request;
+                       mbio->bi_rw = WRITE | do_sync | do_fua | do_discard;
+                       mbio->bi_private = r10_bio;
 
-               cb = blk_check_plugged(raid10_unplug, mddev, sizeof(*plug));
-               if (cb)
-                       plug = container_of(cb, struct raid10_plug_cb, cb);
-               else
-                       plug = NULL;
-               spin_lock_irqsave(&conf->device_lock, flags);
-               if (plug) {
-                       bio_list_add(&plug->pending, mbio);
-                       plug->pending_cnt++;
-               } else {
+                       atomic_inc(&r10_bio->remaining);
+                       spin_lock_irqsave(&conf->device_lock, flags);
                        bio_list_add(&conf->pending_bio_list, mbio);
                        conf->pending_count++;
+                       spin_unlock_irqrestore(&conf->device_lock, flags);
+                       if (!mddev_check_plugged(mddev))
+                               md_wakeup_thread(mddev->thread);
                }
-               spin_unlock_irqrestore(&conf->device_lock, flags);
-               if (!plug)
-                       md_wakeup_thread(mddev->thread);
-
-               if (!r10_bio->devs[i].repl_bio)
-                       continue;
-
-               mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
-               md_trim_bio(mbio, r10_bio->sector - bio->bi_sector,
-                           max_sectors);
-               r10_bio->devs[i].repl_bio = mbio;
-
-               /* We are actively writing to the original device
-                * so it cannot disappear, so the replacement cannot
-                * become NULL here
-                */
-               mbio->bi_sector = (r10_bio->devs[i].addr +
-                                  choose_data_offset(
-                                          r10_bio,
-                                          conf->mirrors[d].replacement));
-               mbio->bi_bdev = conf->mirrors[d].replacement->bdev;
-               mbio->bi_end_io = raid10_end_write_request;
-               mbio->bi_rw = WRITE | do_sync | do_fua | do_discard;
-               mbio->bi_private = r10_bio;
-
-               atomic_inc(&r10_bio->remaining);
-               spin_lock_irqsave(&conf->device_lock, flags);
-               bio_list_add(&conf->pending_bio_list, mbio);
-               conf->pending_count++;
-               spin_unlock_irqrestore(&conf->device_lock, flags);
-               if (!mddev_check_plugged(mddev))
-                       md_wakeup_thread(mddev->thread);
        }
 
        /* Don't remove the bias on 'remaining' (one_write_done) until
@@ -1783,7 +1790,7 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)
                clear_bit(Unmerged, &rdev->flags);
        }
        md_integrity_add_rdev(rdev, mddev);
-       if (blk_queue_discard(bdev_get_queue(rdev->bdev)))
+       if (mddev->queue && blk_queue_discard(bdev_get_queue(rdev->bdev)))
                queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
 
        print_conf(conf);
@@ -3613,11 +3620,14 @@ static int run(struct mddev *mddev)
                        discard_supported = true;
        }
 
-       if (discard_supported)
-               queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
-       else
-               queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
-
+       if (mddev->queue) {
+               if (discard_supported)
+                       queue_flag_set_unlocked(QUEUE_FLAG_DISCARD,
+                                               mddev->queue);
+               else
+                       queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD,
+                                                 mddev->queue);
+       }
        /* need to check that every block has at least one working mirror */
        if (!enough(conf, -1)) {
                printk(KERN_ERR "md/raid10:%s: not enough operational mirrors.\n",
index c5439dc..a450268 100644 (file)
@@ -2774,10 +2774,12 @@ static void handle_stripe_clean_event(struct r5conf *conf,
                        dev = &sh->dev[i];
                        if (!test_bit(R5_LOCKED, &dev->flags) &&
                            (test_bit(R5_UPTODATE, &dev->flags) ||
-                            test_and_clear_bit(R5_Discard, &dev->flags))) {
+                            test_bit(R5_Discard, &dev->flags))) {
                                /* We can return any write requests */
                                struct bio *wbi, *wbi2;
                                pr_debug("Return write for disc %d\n", i);
+                               if (test_and_clear_bit(R5_Discard, &dev->flags))
+                                       clear_bit(R5_UPTODATE, &dev->flags);
                                wbi = dev->written;
                                dev->written = NULL;
                                while (wbi && wbi->bi_sector <
@@ -2795,7 +2797,8 @@ static void handle_stripe_clean_event(struct r5conf *conf,
                                         !test_bit(STRIPE_DEGRADED, &sh->state),
                                                0);
                        }
-               }
+               } else if (test_bit(R5_Discard, &sh->dev[i].flags))
+                       clear_bit(R5_Discard, &sh->dev[i].flags);
 
        if (test_and_clear_bit(STRIPE_FULL_WRITE, &sh->state))
                if (atomic_dec_and_test(&conf->pending_full_writes))
@@ -3490,40 +3493,6 @@ static void handle_stripe(struct stripe_head *sh)
                        handle_failed_sync(conf, sh, &s);
        }
 
-       /*
-        * might be able to return some write requests if the parity blocks
-        * are safe, or on a failed drive
-        */
-       pdev = &sh->dev[sh->pd_idx];
-       s.p_failed = (s.failed >= 1 && s.failed_num[0] == sh->pd_idx)
-               || (s.failed >= 2 && s.failed_num[1] == sh->pd_idx);
-       qdev = &sh->dev[sh->qd_idx];
-       s.q_failed = (s.failed >= 1 && s.failed_num[0] == sh->qd_idx)
-               || (s.failed >= 2 && s.failed_num[1] == sh->qd_idx)
-               || conf->level < 6;
-
-       if (s.written &&
-           (s.p_failed || ((test_bit(R5_Insync, &pdev->flags)
-                            && !test_bit(R5_LOCKED, &pdev->flags)
-                            && (test_bit(R5_UPTODATE, &pdev->flags) ||
-                                test_bit(R5_Discard, &pdev->flags))))) &&
-           (s.q_failed || ((test_bit(R5_Insync, &qdev->flags)
-                            && !test_bit(R5_LOCKED, &qdev->flags)
-                            && (test_bit(R5_UPTODATE, &qdev->flags) ||
-                                test_bit(R5_Discard, &qdev->flags))))))
-               handle_stripe_clean_event(conf, sh, disks, &s.return_bi);
-
-       /* Now we might consider reading some blocks, either to check/generate
-        * parity, or to satisfy requests
-        * or to load a block that is being partially written.
-        */
-       if (s.to_read || s.non_overwrite
-           || (conf->level == 6 && s.to_write && s.failed)
-           || (s.syncing && (s.uptodate + s.compute < disks))
-           || s.replacing
-           || s.expanding)
-               handle_stripe_fill(sh, &s, disks);
-
        /* Now we check to see if any write operations have recently
         * completed
         */
@@ -3561,6 +3530,40 @@ static void handle_stripe(struct stripe_head *sh)
                        s.dec_preread_active = 1;
        }
 
+       /*
+        * might be able to return some write requests if the parity blocks
+        * are safe, or on a failed drive
+        */
+       pdev = &sh->dev[sh->pd_idx];
+       s.p_failed = (s.failed >= 1 && s.failed_num[0] == sh->pd_idx)
+               || (s.failed >= 2 && s.failed_num[1] == sh->pd_idx);
+       qdev = &sh->dev[sh->qd_idx];
+       s.q_failed = (s.failed >= 1 && s.failed_num[0] == sh->qd_idx)
+               || (s.failed >= 2 && s.failed_num[1] == sh->qd_idx)
+               || conf->level < 6;
+
+       if (s.written &&
+           (s.p_failed || ((test_bit(R5_Insync, &pdev->flags)
+                            && !test_bit(R5_LOCKED, &pdev->flags)
+                            && (test_bit(R5_UPTODATE, &pdev->flags) ||
+                                test_bit(R5_Discard, &pdev->flags))))) &&
+           (s.q_failed || ((test_bit(R5_Insync, &qdev->flags)
+                            && !test_bit(R5_LOCKED, &qdev->flags)
+                            && (test_bit(R5_UPTODATE, &qdev->flags) ||
+                                test_bit(R5_Discard, &qdev->flags))))))
+               handle_stripe_clean_event(conf, sh, disks, &s.return_bi);
+
+       /* Now we might consider reading some blocks, either to check/generate
+        * parity, or to satisfy requests
+        * or to load a block that is being partially written.
+        */
+       if (s.to_read || s.non_overwrite
+           || (conf->level == 6 && s.to_write && s.failed)
+           || (s.syncing && (s.uptodate + s.compute < disks))
+           || s.replacing
+           || s.expanding)
+               handle_stripe_fill(sh, &s, disks);
+
        /* Now to consider new write requests and what else, if anything
         * should be read.  We do not handle new writes when:
         * 1/ A 'write' operation (copy+xor) is already in flight.
@@ -5529,6 +5532,10 @@ static int run(struct mddev *mddev)
                 * discard data disk but write parity disk
                 */
                stripe = stripe * PAGE_SIZE;
+               /* Round up to power of 2, as discard handling
+                * currently assumes that */
+               while ((stripe-1) & stripe)
+                       stripe = (stripe | (stripe-1)) + 1;
                mddev->queue->limits.discard_alignment = stripe;
                mddev->queue->limits.discard_granularity = stripe;
                /*
index dd13e3a..4ef0d80 100644 (file)
@@ -163,19 +163,21 @@ source "drivers/media/common/Kconfig"
 #
 
 config MEDIA_SUBDRV_AUTOSELECT
-       bool "Autoselect analog and hybrid tuner modules to build"
-       depends on MEDIA_TUNER
+       bool "Autoselect tuners and i2c modules to build"
+       depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_CAMERA_SUPPORT
        default y
        help
-         By default, a TV driver auto-selects all possible tuners
-         thar could be used by the driver.
+         By default, a media driver auto-selects all possible i2c
+         devices that are used by any of the supported devices.
 
          This is generally the right thing to do, except when there
-         are strict constraints with regards to the kernel size.
+         are strict constraints with regards to the kernel size,
+         like on embedded systems.
 
-         Use this option with care, as deselecting tuner drivers which
-         are in fact necessary will result in TV devices which cannot
-         be tuned due to lack of the tuning driver.
+         Use this option with care, as deselecting ancillary drivers which
+         are, in fact, necessary will result in the lack of the needed
+         functionality for your device (it may not tune or may not have
+         the need demodulers).
 
          If unsure say Y.
 
index 262dfa5..b551ca3 100644 (file)
@@ -300,15 +300,15 @@ static enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *intp, u32
 {
        u32 m_div, clk_sel;
 
-       dprintk("%s: Mclk set to %d, Quartz = %d\n", __func__, mclk,
-                       intp->quartz);
-
        if (intp == NULL)
                return STV0900_INVALID_HANDLE;
 
        if (intp->errs)
                return STV0900_I2C_ERROR;
 
+       dprintk("%s: Mclk set to %d, Quartz = %d\n", __func__, mclk,
+                       intp->quartz);
+
        clk_sel = ((stv0900_get_bits(intp, F0900_SELX1RATIO) == 1) ? 4 : 6);
        m_div = ((clk_sel * mclk) / intp->quartz) - 1;
        stv0900_write_bits(intp, F0900_M_DIV, m_div);
index 109bc9b..05f8950 100644 (file)
@@ -53,8 +53,7 @@ MODULE_LICENSE("GPL");
 /* ADV7604 system clock frequency */
 #define ADV7604_fsc (28636360)
 
-#define DIGITAL_INPUT ((state->prim_mode == ADV7604_PRIM_MODE_HDMI_COMP) || \
-                       (state->prim_mode == ADV7604_PRIM_MODE_HDMI_GR))
+#define DIGITAL_INPUT (state->mode == ADV7604_MODE_HDMI)
 
 /*
  **********************************************************************
@@ -68,7 +67,7 @@ struct adv7604_state {
        struct v4l2_subdev sd;
        struct media_pad pad;
        struct v4l2_ctrl_handler hdl;
-       enum adv7604_prim_mode prim_mode;
+       enum adv7604_mode mode;
        struct v4l2_dv_timings timings;
        u8 edid[256];
        unsigned edid_blocks;
@@ -77,6 +76,7 @@ struct adv7604_state {
        struct workqueue_struct *work_queues;
        struct delayed_work delayed_work_enable_hotplug;
        bool connector_hdmi;
+       bool restart_stdi_once;
 
        /* i2c clients */
        struct i2c_client *i2c_avlink;
@@ -106,7 +106,6 @@ static const struct v4l2_dv_timings adv7604_timings[] = {
        V4L2_DV_BT_CEA_720X576P50,
        V4L2_DV_BT_CEA_1280X720P24,
        V4L2_DV_BT_CEA_1280X720P25,
-       V4L2_DV_BT_CEA_1280X720P30,
        V4L2_DV_BT_CEA_1280X720P50,
        V4L2_DV_BT_CEA_1280X720P60,
        V4L2_DV_BT_CEA_1920X1080P24,
@@ -115,6 +114,7 @@ static const struct v4l2_dv_timings adv7604_timings[] = {
        V4L2_DV_BT_CEA_1920X1080P50,
        V4L2_DV_BT_CEA_1920X1080P60,
 
+       /* sorted by DMT ID */
        V4L2_DV_BT_DMT_640X350P85,
        V4L2_DV_BT_DMT_640X400P85,
        V4L2_DV_BT_DMT_720X400P85,
@@ -164,6 +164,89 @@ static const struct v4l2_dv_timings adv7604_timings[] = {
        { },
 };
 
+struct adv7604_video_standards {
+       struct v4l2_dv_timings timings;
+       u8 vid_std;
+       u8 v_freq;
+};
+
+/* sorted by number of lines */
+static const struct adv7604_video_standards adv7604_prim_mode_comp[] = {
+       /* { V4L2_DV_BT_CEA_720X480P59_94, 0x0a, 0x00 }, TODO flickering */
+       { V4L2_DV_BT_CEA_720X576P50, 0x0b, 0x00 },
+       { V4L2_DV_BT_CEA_1280X720P50, 0x19, 0x01 },
+       { V4L2_DV_BT_CEA_1280X720P60, 0x19, 0x00 },
+       { V4L2_DV_BT_CEA_1920X1080P24, 0x1e, 0x04 },
+       { V4L2_DV_BT_CEA_1920X1080P25, 0x1e, 0x03 },
+       { V4L2_DV_BT_CEA_1920X1080P30, 0x1e, 0x02 },
+       { V4L2_DV_BT_CEA_1920X1080P50, 0x1e, 0x01 },
+       { V4L2_DV_BT_CEA_1920X1080P60, 0x1e, 0x00 },
+       /* TODO add 1920x1080P60_RB (CVT timing) */
+       { },
+};
+
+/* sorted by number of lines */
+static const struct adv7604_video_standards adv7604_prim_mode_gr[] = {
+       { V4L2_DV_BT_DMT_640X480P60, 0x08, 0x00 },
+       { V4L2_DV_BT_DMT_640X480P72, 0x09, 0x00 },
+       { V4L2_DV_BT_DMT_640X480P75, 0x0a, 0x00 },
+       { V4L2_DV_BT_DMT_640X480P85, 0x0b, 0x00 },
+       { V4L2_DV_BT_DMT_800X600P56, 0x00, 0x00 },
+       { V4L2_DV_BT_DMT_800X600P60, 0x01, 0x00 },
+       { V4L2_DV_BT_DMT_800X600P72, 0x02, 0x00 },
+       { V4L2_DV_BT_DMT_800X600P75, 0x03, 0x00 },
+       { V4L2_DV_BT_DMT_800X600P85, 0x04, 0x00 },
+       { V4L2_DV_BT_DMT_1024X768P60, 0x0c, 0x00 },
+       { V4L2_DV_BT_DMT_1024X768P70, 0x0d, 0x00 },
+       { V4L2_DV_BT_DMT_1024X768P75, 0x0e, 0x00 },
+       { V4L2_DV_BT_DMT_1024X768P85, 0x0f, 0x00 },
+       { V4L2_DV_BT_DMT_1280X1024P60, 0x05, 0x00 },
+       { V4L2_DV_BT_DMT_1280X1024P75, 0x06, 0x00 },
+       { V4L2_DV_BT_DMT_1360X768P60, 0x12, 0x00 },
+       { V4L2_DV_BT_DMT_1366X768P60, 0x13, 0x00 },
+       { V4L2_DV_BT_DMT_1400X1050P60, 0x14, 0x00 },
+       { V4L2_DV_BT_DMT_1400X1050P75, 0x15, 0x00 },
+       { V4L2_DV_BT_DMT_1600X1200P60, 0x16, 0x00 }, /* TODO not tested */
+       /* TODO add 1600X1200P60_RB (not a DMT timing) */
+       { V4L2_DV_BT_DMT_1680X1050P60, 0x18, 0x00 },
+       { V4L2_DV_BT_DMT_1920X1200P60_RB, 0x19, 0x00 }, /* TODO not tested */
+       { },
+};
+
+/* sorted by number of lines */
+static const struct adv7604_video_standards adv7604_prim_mode_hdmi_comp[] = {
+       { V4L2_DV_BT_CEA_720X480P59_94, 0x0a, 0x00 },
+       { V4L2_DV_BT_CEA_720X576P50, 0x0b, 0x00 },
+       { V4L2_DV_BT_CEA_1280X720P50, 0x13, 0x01 },
+       { V4L2_DV_BT_CEA_1280X720P60, 0x13, 0x00 },
+       { V4L2_DV_BT_CEA_1920X1080P24, 0x1e, 0x04 },
+       { V4L2_DV_BT_CEA_1920X1080P25, 0x1e, 0x03 },
+       { V4L2_DV_BT_CEA_1920X1080P30, 0x1e, 0x02 },
+       { V4L2_DV_BT_CEA_1920X1080P50, 0x1e, 0x01 },
+       { V4L2_DV_BT_CEA_1920X1080P60, 0x1e, 0x00 },
+       { },
+};
+
+/* sorted by number of lines */
+static const struct adv7604_video_standards adv7604_prim_mode_hdmi_gr[] = {
+       { V4L2_DV_BT_DMT_640X480P60, 0x08, 0x00 },
+       { V4L2_DV_BT_DMT_640X480P72, 0x09, 0x00 },
+       { V4L2_DV_BT_DMT_640X480P75, 0x0a, 0x00 },
+       { V4L2_DV_BT_DMT_640X480P85, 0x0b, 0x00 },
+       { V4L2_DV_BT_DMT_800X600P56, 0x00, 0x00 },
+       { V4L2_DV_BT_DMT_800X600P60, 0x01, 0x00 },
+       { V4L2_DV_BT_DMT_800X600P72, 0x02, 0x00 },
+       { V4L2_DV_BT_DMT_800X600P75, 0x03, 0x00 },
+       { V4L2_DV_BT_DMT_800X600P85, 0x04, 0x00 },
+       { V4L2_DV_BT_DMT_1024X768P60, 0x0c, 0x00 },
+       { V4L2_DV_BT_DMT_1024X768P70, 0x0d, 0x00 },
+       { V4L2_DV_BT_DMT_1024X768P75, 0x0e, 0x00 },
+       { V4L2_DV_BT_DMT_1024X768P85, 0x0f, 0x00 },
+       { V4L2_DV_BT_DMT_1280X1024P60, 0x05, 0x00 },
+       { V4L2_DV_BT_DMT_1280X1024P75, 0x06, 0x00 },
+       { },
+};
+
 /* ----------------------------------------------------------------------- */
 
 static inline struct adv7604_state *to_state(struct v4l2_subdev *sd)
@@ -672,64 +755,144 @@ static int adv7604_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd)
                                ((io_read(sd, 0x6f) & 0x10) >> 4));
 }
 
-static void configure_free_run(struct v4l2_subdev *sd, const struct v4l2_bt_timings *timings)
+static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd,
+               u8 prim_mode,
+               const struct adv7604_video_standards *predef_vid_timings,
+               const struct v4l2_dv_timings *timings)
+{
+       struct adv7604_state *state = to_state(sd);
+       int i;
+
+       for (i = 0; predef_vid_timings[i].timings.bt.width; i++) {
+               if (!v4l_match_dv_timings(timings, &predef_vid_timings[i].timings,
+                                       DIGITAL_INPUT ? 250000 : 1000000))
+                       continue;
+               io_write(sd, 0x00, predef_vid_timings[i].vid_std); /* video std */
+               io_write(sd, 0x01, (predef_vid_timings[i].v_freq << 4) +
+                               prim_mode); /* v_freq and prim mode */
+               return 0;
+       }
+
+       return -1;
+}
+
+static int configure_predefined_video_timings(struct v4l2_subdev *sd,
+               struct v4l2_dv_timings *timings)
 {
+       struct adv7604_state *state = to_state(sd);
+       int err;
+
+       v4l2_dbg(1, debug, sd, "%s", __func__);
+
+       /* reset to default values */
+       io_write(sd, 0x16, 0x43);
+       io_write(sd, 0x17, 0x5a);
+       /* disable embedded syncs for auto graphics mode */
+       cp_write_and_or(sd, 0x81, 0xef, 0x00);
+       cp_write(sd, 0x8f, 0x00);
+       cp_write(sd, 0x90, 0x00);
+       cp_write(sd, 0xa2, 0x00);
+       cp_write(sd, 0xa3, 0x00);
+       cp_write(sd, 0xa4, 0x00);
+       cp_write(sd, 0xa5, 0x00);
+       cp_write(sd, 0xa6, 0x00);
+       cp_write(sd, 0xa7, 0x00);
+       cp_write(sd, 0xab, 0x00);
+       cp_write(sd, 0xac, 0x00);
+
+       switch (state->mode) {
+       case ADV7604_MODE_COMP:
+       case ADV7604_MODE_GR:
+               err = find_and_set_predefined_video_timings(sd,
+                               0x01, adv7604_prim_mode_comp, timings);
+               if (err)
+                       err = find_and_set_predefined_video_timings(sd,
+                                       0x02, adv7604_prim_mode_gr, timings);
+               break;
+       case ADV7604_MODE_HDMI:
+               err = find_and_set_predefined_video_timings(sd,
+                               0x05, adv7604_prim_mode_hdmi_comp, timings);
+               if (err)
+                       err = find_and_set_predefined_video_timings(sd,
+                                       0x06, adv7604_prim_mode_hdmi_gr, timings);
+               break;
+       default:
+               v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
+                               __func__, state->mode);
+               err = -1;
+               break;
+       }
+
+
+       return err;
+}
+
+static void configure_custom_video_timings(struct v4l2_subdev *sd,
+               const struct v4l2_bt_timings *bt)
+{
+       struct adv7604_state *state = to_state(sd);
        struct i2c_client *client = v4l2_get_subdevdata(sd);
-       u32 width = htotal(timings);
-       u32 height = vtotal(timings);
-       u16 ch1_fr_ll = (((u32)timings->pixelclock / 100) > 0) ?
-               ((width * (ADV7604_fsc / 100)) / ((u32)timings->pixelclock / 100)) : 0;
+       u32 width = htotal(bt);
+       u32 height = vtotal(bt);
+       u16 cp_start_sav = bt->hsync + bt->hbackporch - 4;
+       u16 cp_start_eav = width - bt->hfrontporch;
+       u16 cp_start_vbi = height - bt->vfrontporch;
+       u16 cp_end_vbi = bt->vsync + bt->vbackporch;
+       u16 ch1_fr_ll = (((u32)bt->pixelclock / 100) > 0) ?
+               ((width * (ADV7604_fsc / 100)) / ((u32)bt->pixelclock / 100)) : 0;
+       const u8 pll[2] = {
+               0xc0 | ((width >> 8) & 0x1f),
+               width & 0xff
+       };
 
        v4l2_dbg(2, debug, sd, "%s\n", __func__);
 
-       cp_write(sd, 0x8f, (ch1_fr_ll >> 8) & 0x7);     /* CH1_FR_LL */
-       cp_write(sd, 0x90, ch1_fr_ll & 0xff);           /* CH1_FR_LL */
-       cp_write(sd, 0xab, (height >> 4) & 0xff); /* CP_LCOUNT_MAX */
-       cp_write(sd, 0xac, (height & 0x0f) << 4); /* CP_LCOUNT_MAX */
-       /* TODO support interlaced */
-       cp_write(sd, 0x91, 0x10);       /* INTERLACED */
-
-       /* Should only be set in auto-graphics mode [REF_02 p. 91-92] */
-       if ((io_read(sd, 0x00) == 0x07) && (io_read(sd, 0x01) == 0x02)) {
-               u16 cp_start_sav, cp_start_eav, cp_start_vbi, cp_end_vbi;
-               const u8 pll[2] = {
-                       (0xc0 | ((width >> 8) & 0x1f)),
-                       (width & 0xff)
-               };
+       switch (state->mode) {
+       case ADV7604_MODE_COMP:
+       case ADV7604_MODE_GR:
+               /* auto graphics */
+               io_write(sd, 0x00, 0x07); /* video std */
+               io_write(sd, 0x01, 0x02); /* prim mode */
+               /* enable embedded syncs for auto graphics mode */
+               cp_write_and_or(sd, 0x81, 0xef, 0x10);
 
+               /* Should only be set in auto-graphics mode [REF_02, p. 91-92] */
                /* setup PLL_DIV_MAN_EN and PLL_DIV_RATIO */
                /* IO-map reg. 0x16 and 0x17 should be written in sequence */
                if (adv_smbus_write_i2c_block_data(client, 0x16, 2, pll)) {
                        v4l2_err(sd, "writing to reg 0x16 and 0x17 failed\n");
-                       return;
+                       break;
                }
 
                /* active video - horizontal timing */
-               cp_start_sav = timings->hsync + timings->hbackporch - 4;
-               cp_start_eav = width - timings->hfrontporch;
                cp_write(sd, 0xa2, (cp_start_sav >> 4) & 0xff);
-               cp_write(sd, 0xa3, ((cp_start_sav & 0x0f) << 4) | ((cp_start_eav >> 8) & 0x0f));
+               cp_write(sd, 0xa3, ((cp_start_sav & 0x0f) << 4) |
+                                       ((cp_start_eav >> 8) & 0x0f));
                cp_write(sd, 0xa4, cp_start_eav & 0xff);
 
                /* active video - vertical timing */
-               cp_start_vbi = height - timings->vfrontporch;
-               cp_end_vbi = timings->vsync + timings->vbackporch;
                cp_write(sd, 0xa5, (cp_start_vbi >> 4) & 0xff);
-               cp_write(sd, 0xa6, ((cp_start_vbi & 0xf) << 4) | ((cp_end_vbi >> 8) & 0xf));
+               cp_write(sd, 0xa6, ((cp_start_vbi & 0xf) << 4) |
+                                       ((cp_end_vbi >> 8) & 0xf));
                cp_write(sd, 0xa7, cp_end_vbi & 0xff);
-       } else {
-               /* reset to default values */
-               io_write(sd, 0x16, 0x43);
-               io_write(sd, 0x17, 0x5a);
-               cp_write(sd, 0xa2, 0x00);
-               cp_write(sd, 0xa3, 0x00);
-               cp_write(sd, 0xa4, 0x00);
-               cp_write(sd, 0xa5, 0x00);
-               cp_write(sd, 0xa6, 0x00);
-               cp_write(sd, 0xa7, 0x00);
+               break;
+       case ADV7604_MODE_HDMI:
+               /* set default prim_mode/vid_std for HDMI
+                  accoring to [REF_03, c. 4.2] */
+               io_write(sd, 0x00, 0x02); /* video std */
+               io_write(sd, 0x01, 0x06); /* prim mode */
+               break;
+       default:
+               v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
+                               __func__, state->mode);
+               break;
        }
-}
 
+       cp_write(sd, 0x8f, (ch1_fr_ll >> 8) & 0x7);
+       cp_write(sd, 0x90, ch1_fr_ll & 0xff);
+       cp_write(sd, 0xab, (height >> 4) & 0xff);
+       cp_write(sd, 0xac, (height & 0x0f) << 4);
+}
 
 static void set_rgb_quantization_range(struct v4l2_subdev *sd)
 {
@@ -738,12 +901,7 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
        switch (state->rgb_quantization_range) {
        case V4L2_DV_RGB_RANGE_AUTO:
                /* automatic */
-               if ((hdmi_read(sd, 0x05) & 0x80) ||
-                               (state->prim_mode == ADV7604_PRIM_MODE_COMP) ||
-                               (state->prim_mode == ADV7604_PRIM_MODE_RGB)) {
-                       /* receiving HDMI or analog signal */
-                       io_write_and_or(sd, 0x02, 0x0f, 0xf0);
-               } else {
+               if (DIGITAL_INPUT && !(hdmi_read(sd, 0x05) & 0x80)) {
                        /* receiving DVI-D signal */
 
                        /* ADV7604 selects RGB limited range regardless of
@@ -756,6 +914,9 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
                                /* RGB full range (0-255) */
                                io_write_and_or(sd, 0x02, 0x0f, 0x10);
                        }
+               } else {
+                       /* receiving HDMI or analog signal, set automode */
+                       io_write_and_or(sd, 0x02, 0x0f, 0xf0);
                }
                break;
        case V4L2_DV_RGB_RANGE_LIMITED:
@@ -967,8 +1128,10 @@ static int stdi2dv_timings(struct v4l2_subdev *sd,
                        state->aspect_ratio, timings))
                return 0;
 
-       v4l2_dbg(2, debug, sd, "%s: No format candidate found for lcf=%d, bl = %d\n",
-                       __func__, stdi->lcf, stdi->bl);
+       v4l2_dbg(2, debug, sd,
+               "%s: No format candidate found for lcvs = %d, lcf=%d, bl = %d, %chsync, %cvsync\n",
+               __func__, stdi->lcvs, stdi->lcf, stdi->bl,
+               stdi->hs_pol, stdi->vs_pol);
        return -1;
 }
 
@@ -1123,7 +1286,7 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
                adv7604_fill_optional_dv_timings_fields(sd, timings);
        } else {
                /* find format
-                * Since LCVS values are inaccurate (REF_03, page 275-276),
+                * Since LCVS values are inaccurate [REF_03, p. 275-276],
                 * stdi2dv_timings() is called with lcvs +-1 if the first attempt fails.
                 */
                if (!stdi2dv_timings(sd, &stdi, timings))
@@ -1135,9 +1298,31 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
                stdi.lcvs -= 2;
                v4l2_dbg(1, debug, sd, "%s: lcvs - 1 = %d\n", __func__, stdi.lcvs);
                if (stdi2dv_timings(sd, &stdi, timings)) {
+                       /*
+                        * The STDI block may measure wrong values, especially
+                        * for lcvs and lcf. If the driver can not find any
+                        * valid timing, the STDI block is restarted to measure
+                        * the video timings again. The function will return an
+                        * error, but the restart of STDI will generate a new
+                        * STDI interrupt and the format detection process will
+                        * restart.
+                        */
+                       if (state->restart_stdi_once) {
+                               v4l2_dbg(1, debug, sd, "%s: restart STDI\n", __func__);
+                               /* TODO restart STDI for Sync Channel 2 */
+                               /* enter one-shot mode */
+                               cp_write_and_or(sd, 0x86, 0xf9, 0x00);
+                               /* trigger STDI restart */
+                               cp_write_and_or(sd, 0x86, 0xf9, 0x04);
+                               /* reset to continuous mode */
+                               cp_write_and_or(sd, 0x86, 0xf9, 0x02);
+                               state->restart_stdi_once = false;
+                               return -ENOLINK;
+                       }
                        v4l2_dbg(1, debug, sd, "%s: format not supported\n", __func__);
                        return -ERANGE;
                }
+               state->restart_stdi_once = true;
        }
 found:
 
@@ -1166,6 +1351,7 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
 {
        struct adv7604_state *state = to_state(sd);
        struct v4l2_bt_timings *bt;
+       int err;
 
        if (!timings)
                return -EINVAL;
@@ -1178,12 +1364,20 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
                                __func__, (u32)bt->pixelclock);
                return -ERANGE;
        }
+
        adv7604_fill_optional_dv_timings_fields(sd, timings);
 
        state->timings = *timings;
 
-       /* freerun */
-       configure_free_run(sd, bt);
+       cp_write(sd, 0x91, bt->interlaced ? 0x50 : 0x10);
+
+       /* Use prim_mode and vid_std when available */
+       err = configure_predefined_video_timings(sd, timings);
+       if (err) {
+               /* custom settings when the video format
+                does not have prim_mode/vid_std */
+               configure_custom_video_timings(sd, bt);
+       }
 
        set_rgb_quantization_range(sd);
 
@@ -1203,24 +1397,25 @@ static int adv7604_g_dv_timings(struct v4l2_subdev *sd,
        return 0;
 }
 
-static void enable_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mode)
+static void enable_input(struct v4l2_subdev *sd)
 {
-       switch (prim_mode) {
-       case ADV7604_PRIM_MODE_COMP:
-       case ADV7604_PRIM_MODE_RGB:
+       struct adv7604_state *state = to_state(sd);
+
+       switch (state->mode) {
+       case ADV7604_MODE_COMP:
+       case ADV7604_MODE_GR:
                /* enable */
                io_write(sd, 0x15, 0xb0);   /* Disable Tristate of Pins (no audio) */
                break;
-       case ADV7604_PRIM_MODE_HDMI_COMP:
-       case ADV7604_PRIM_MODE_HDMI_GR:
+       case ADV7604_MODE_HDMI:
                /* enable */
                hdmi_write(sd, 0x1a, 0x0a); /* Unmute audio */
                hdmi_write(sd, 0x01, 0x00); /* Enable HDMI clock terminators */
                io_write(sd, 0x15, 0xa0);   /* Disable Tristate of Pins */
                break;
        default:
-               v4l2_err(sd, "%s: reserved primary mode 0x%0x\n",
-                               __func__, prim_mode);
+               v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
+                               __func__, state->mode);
                break;
        }
 }
@@ -1233,17 +1428,13 @@ static void disable_input(struct v4l2_subdev *sd)
        hdmi_write(sd, 0x01, 0x78); /* Disable HDMI clock terminators */
 }
 
-static void select_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mode)
+static void select_input(struct v4l2_subdev *sd)
 {
-       switch (prim_mode) {
-       case ADV7604_PRIM_MODE_COMP:
-       case ADV7604_PRIM_MODE_RGB:
-               /* set mode and select free run resolution */
-               io_write(sd, 0x00, 0x07); /* video std */
-               io_write(sd, 0x01, 0x02); /* prim mode */
-               /* enable embedded syncs for auto graphics mode */
-               cp_write_and_or(sd, 0x81, 0xef, 0x10);
+       struct adv7604_state *state = to_state(sd);
 
+       switch (state->mode) {
+       case ADV7604_MODE_COMP:
+       case ADV7604_MODE_GR:
                /* reset ADI recommended settings for HDMI: */
                /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
                hdmi_write(sd, 0x0d, 0x04); /* HDMI filter optimization */
@@ -1271,16 +1462,7 @@ static void select_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mod
                cp_write(sd, 0x40, 0x5c); /* CP core pre-gain control. Graphics mode */
                break;
 
-       case ADV7604_PRIM_MODE_HDMI_COMP:
-       case ADV7604_PRIM_MODE_HDMI_GR:
-               /* set mode and select free run resolution */
-               /* video std */
-               io_write(sd, 0x00,
-                       (prim_mode == ADV7604_PRIM_MODE_HDMI_GR) ? 0x02 : 0x1e);
-               io_write(sd, 0x01, prim_mode); /* prim mode */
-               /* disable embedded syncs for auto graphics mode */
-               cp_write_and_or(sd, 0x81, 0xef, 0x00);
-
+       case ADV7604_MODE_HDMI:
                /* set ADI recommended settings for HDMI: */
                /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
                hdmi_write(sd, 0x0d, 0x84); /* HDMI filter optimization */
@@ -1309,7 +1491,8 @@ static void select_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mod
 
                break;
        default:
-               v4l2_err(sd, "%s: reserved primary mode 0x%0x\n", __func__, prim_mode);
+               v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
+                               __func__, state->mode);
                break;
        }
 }
@@ -1321,26 +1504,13 @@ static int adv7604_s_routing(struct v4l2_subdev *sd,
 
        v4l2_dbg(2, debug, sd, "%s: input %d", __func__, input);
 
-       switch (input) {
-       case 0:
-               /* TODO select HDMI_COMP or HDMI_GR */
-               state->prim_mode = ADV7604_PRIM_MODE_HDMI_COMP;
-               break;
-       case 1:
-               state->prim_mode = ADV7604_PRIM_MODE_RGB;
-               break;
-       case 2:
-               state->prim_mode = ADV7604_PRIM_MODE_COMP;
-               break;
-       default:
-               return -EINVAL;
-       }
+       state->mode = input;
 
        disable_input(sd);
 
-       select_input(sd, state->prim_mode);
+       select_input(sd);
 
-       enable_input(sd, state->prim_mode);
+       enable_input(sd);
 
        return 0;
 }
@@ -1549,8 +1719,9 @@ static int adv7604_log_status(struct v4l2_subdev *sd)
        v4l2_info(sd, "CP locked: %s\n", no_lock_cp(sd) ? "false" : "true");
        v4l2_info(sd, "CP free run: %s\n",
                        (!!(cp_read(sd, 0xff) & 0x10) ? "on" : "off"));
-       v4l2_info(sd, "Prim-mode = 0x%x, video std = 0x%x\n",
-                       io_read(sd, 0x01) & 0x0f, io_read(sd, 0x00) & 0x3f);
+       v4l2_info(sd, "Prim-mode = 0x%x, video std = 0x%x, v_freq = 0x%x\n",
+                       io_read(sd, 0x01) & 0x0f, io_read(sd, 0x00) & 0x3f,
+                       (io_read(sd, 0x01) & 0x70) >> 4);
 
        v4l2_info(sd, "-----Video Timings-----\n");
        if (read_stdi(sd, &stdi))
@@ -1712,9 +1883,9 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
        cp_write(sd, 0xba, (pdata->hdmi_free_run_mode << 1) | 0x01); /* HDMI free run */
        cp_write(sd, 0xf3, 0xdc); /* Low threshold to enter/exit free run mode */
        cp_write(sd, 0xf9, 0x23); /*  STDI ch. 1 - LCVS change threshold -
-                                     ADI recommended setting [REF_01 c. 2.3.3] */
+                                     ADI recommended setting [REF_01, c. 2.3.3] */
        cp_write(sd, 0x45, 0x23); /*  STDI ch. 2 - LCVS change threshold -
-                                     ADI recommended setting [REF_01 c. 2.3.3] */
+                                     ADI recommended setting [REF_01, c. 2.3.3] */
        cp_write(sd, 0xc9, 0x2d); /* use prim_mode and vid_std as free run resolution
                                     for digital formats */
 
@@ -1724,11 +1895,6 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
        afe_write(sd, 0x02, pdata->ain_sel); /* Select analog input muxing mode */
        io_write_and_or(sd, 0x30, ~(1 << 4), pdata->output_bus_lsb_to_msb << 4);
 
-       state->prim_mode = pdata->prim_mode;
-       select_input(sd, pdata->prim_mode);
-
-       enable_input(sd, pdata->prim_mode);
-
        /* interrupts */
        io_write(sd, 0x40, 0xc2); /* Configure INT1 */
        io_write(sd, 0x41, 0xd7); /* STDI irq for any change, disable INT2 */
@@ -1883,6 +2049,7 @@ static int adv7604_probe(struct i2c_client *client,
                v4l2_err(sd, "failed to create all i2c clients\n");
                goto err_i2c;
        }
+       state->restart_stdi_once = true;
 
        /* work queues */
        state->work_queues = create_singlethread_workqueue(client->name);
index 13057b9..333ef17 100644 (file)
@@ -263,9 +263,14 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
                if (ret & 1) /* Autoexposure */
                        ret = reg_write(client, mt9v022->reg->max_total_shutter_width,
                                        rect.height + mt9v022->y_skip_top + 43);
-               else
-                       ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH,
-                                       rect.height + mt9v022->y_skip_top + 43);
+               /*
+                * If autoexposure is off, there is no need to set
+                * MT9V022_TOTAL_SHUTTER_WIDTH here. Autoexposure can be off
+                * only if the user has set exposure manually, using the
+                * V4L2_CID_EXPOSURE_AUTO with the value V4L2_EXPOSURE_MANUAL.
+                * In this case the register MT9V022_TOTAL_SHUTTER_WIDTH
+                * already contains the correct value.
+                */
        }
        /* Setup frame format: defaults apart from width and height */
        if (!ret)
index bfec9e6..19cbb12 100644 (file)
@@ -965,8 +965,10 @@ static struct platform_device_id gsc_driver_ids[] = {
 MODULE_DEVICE_TABLE(platform, gsc_driver_ids);
 
 static const struct of_device_id exynos_gsc_match[] = {
-       { .compatible = "samsung,exynos5250-gsc",
-       .data = &gsc_v_100_drvdata, },
+       {
+               .compatible = "samsung,exynos5-gsc",
+               .data = &gsc_v_100_drvdata,
+       },
        {},
 };
 MODULE_DEVICE_TABLE(of, exynos_gsc_match);
index 3c7f005..c065d04 100644 (file)
@@ -657,8 +657,7 @@ static int gsc_m2m_release(struct file *file)
        pr_debug("pid: %d, state: 0x%lx, refcnt= %d",
                task_pid_nr(current), gsc->state, gsc->m2m.refcnt);
 
-       if (mutex_lock_interruptible(&gsc->lock))
-               return -ERESTARTSYS;
+       mutex_lock(&gsc->lock);
 
        v4l2_m2m_ctx_release(ctx->m2m_ctx);
        gsc_ctrls_delete(ctx);
@@ -732,6 +731,7 @@ int gsc_register_m2m_device(struct gsc_dev *gsc)
        gsc->vdev.ioctl_ops     = &gsc_m2m_ioctl_ops;
        gsc->vdev.release       = video_device_release_empty;
        gsc->vdev.lock          = &gsc->lock;
+       gsc->vdev.vfl_dir       = VFL_DIR_M2M;
        snprintf(gsc->vdev.name, sizeof(gsc->vdev.name), "%s.%d:m2m",
                                        GSC_MODULE_NAME, gsc->id);
 
index 533e994..4678f9a 100644 (file)
 #define GSC_IN_ROT_YFLIP               (2 << 16)
 #define GSC_IN_ROT_XFLIP               (1 << 16)
 #define GSC_IN_RGB_TYPE_MASK           (3 << 14)
-#define GSC_IN_RGB_HD_WIDE             (3 << 14)
-#define GSC_IN_RGB_HD_NARROW           (2 << 14)
-#define GSC_IN_RGB_SD_WIDE             (1 << 14)
-#define GSC_IN_RGB_SD_NARROW           (0 << 14)
+#define GSC_IN_RGB_HD_NARROW           (3 << 14)
+#define GSC_IN_RGB_HD_WIDE             (2 << 14)
+#define GSC_IN_RGB_SD_NARROW           (1 << 14)
+#define GSC_IN_RGB_SD_WIDE             (0 << 14)
 #define GSC_IN_YUV422_1P_ORDER_MASK    (1 << 13)
 #define GSC_IN_YUV422_1P_ORDER_LSB_Y   (0 << 13)
 #define GSC_IN_YUV422_1P_OEDER_LSB_C   (1 << 13)
 #define GSC_OUT_GLOBAL_ALPHA_MASK      (0xff << 24)
 #define GSC_OUT_GLOBAL_ALPHA(x)                ((x) << 24)
 #define GSC_OUT_RGB_TYPE_MASK          (3 << 10)
-#define GSC_OUT_RGB_HD_NARROW          (3 << 10)
-#define GSC_OUT_RGB_HD_WIDE            (2 << 10)
-#define GSC_OUT_RGB_SD_NARROW          (1 << 10)
-#define GSC_OUT_RGB_SD_WIDE            (0 << 10)
+#define GSC_OUT_RGB_HD_WIDE            (3 << 10)
+#define GSC_OUT_RGB_HD_NARROW          (2 << 10)
+#define GSC_OUT_RGB_SD_WIDE            (1 << 10)
+#define GSC_OUT_RGB_SD_NARROW          (0 << 10)
 #define GSC_OUT_YUV422_1P_ORDER_MASK   (1 << 9)
 #define GSC_OUT_YUV422_1P_ORDER_LSB_Y  (0 << 9)
 #define GSC_OUT_YUV422_1P_OEDER_LSB_C  (1 << 9)
index 60181ab..aa9df9d 100644 (file)
@@ -1706,7 +1706,7 @@ static long ccdc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
 }
 
 static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
-                               const struct v4l2_event_subscription *sub)
+                               struct v4l2_event_subscription *sub)
 {
        if (sub->type != V4L2_EVENT_FRAME_SYNC)
                return -EINVAL;
@@ -1719,7 +1719,7 @@ static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
 }
 
 static int ccdc_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
-                                 const struct v4l2_event_subscription *sub)
+                                 struct v4l2_event_subscription *sub)
 {
        return v4l2_event_unsubscribe(fh, sub);
 }
index d7ac76b..b8640be 100644 (file)
@@ -1025,7 +1025,7 @@ void omap3isp_stat_dma_isr(struct ispstat *stat)
 
 int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
                                  struct v4l2_fh *fh,
-                                 const struct v4l2_event_subscription *sub)
+                                 struct v4l2_event_subscription *sub)
 {
        struct ispstat *stat = v4l2_get_subdevdata(subdev);
 
@@ -1037,7 +1037,7 @@ int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
 
 int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
                                    struct v4l2_fh *fh,
-                                   const struct v4l2_event_subscription *sub)
+                                   struct v4l2_event_subscription *sub)
 {
        return v4l2_event_unsubscribe(fh, sub);
 }
index a6fe653..9b7c865 100644 (file)
@@ -147,10 +147,10 @@ int omap3isp_stat_init(struct ispstat *stat, const char *name,
 void omap3isp_stat_cleanup(struct ispstat *stat);
 int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
                                  struct v4l2_fh *fh,
-                                 const struct v4l2_event_subscription *sub);
+                                 struct v4l2_event_subscription *sub);
 int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
                                    struct v4l2_fh *fh,
-                                   const struct v4l2_event_subscription *sub);
+                                   struct v4l2_event_subscription *sub);
 int omap3isp_stat_s_stream(struct v4l2_subdev *subdev, int enable);
 
 int omap3isp_stat_busy(struct ispstat *stat);
index a0b737f..75cd309 100644 (file)
@@ -792,7 +792,7 @@ isp_video_get_crop(struct file *file, void *fh, struct v4l2_crop *crop)
 }
 
 static int
-isp_video_set_crop(struct file *file, void *fh, struct v4l2_crop *crop)
+isp_video_set_crop(struct file *file, void *fh, const struct v4l2_crop *crop)
 {
        struct isp_video *video = video_drvdata(file);
        struct v4l2_subdev *subdev;
index 8f090a8..c16b20d 100644 (file)
@@ -24,6 +24,7 @@ config VIDEO_S5P_FIMC
 config VIDEO_S5P_MIPI_CSIS
        tristate "S5P/EXYNOS MIPI-CSI2 receiver (MIPI-CSIS) driver"
        depends on REGULATOR
+       select S5P_SETUP_MIPIPHY
        help
          This is a V4L2 driver for Samsung S5P and EXYNOS4 SoC MIPI-CSI2
          receiver (MIPI-CSIS) devices.
index 367efd1..891ee87 100644 (file)
@@ -556,8 +556,7 @@ static int fimc_capture_close(struct file *file)
 
        dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state);
 
-       if (mutex_lock_interruptible(&fimc->lock))
-               return -ERESTARTSYS;
+       mutex_lock(&fimc->lock);
 
        if (--fimc->vid_cap.refcnt == 0) {
                clear_bit(ST_CAPT_BUSY, &fimc->state);
@@ -1736,7 +1735,9 @@ static int fimc_register_capture_device(struct fimc_dev *fimc,
        q->mem_ops = &vb2_dma_contig_memops;
        q->buf_struct_size = sizeof(struct fimc_vid_buffer);
 
-       vb2_queue_init(q);
+       ret = vb2_queue_init(q);
+       if (ret)
+               goto err_ent;
 
        vid_cap->vd_pad.flags = MEDIA_PAD_FL_SINK;
        ret = media_entity_init(&vfd->entity, 1, &vid_cap->vd_pad, 0);
@@ -1772,9 +1773,13 @@ static int fimc_capture_subdev_registered(struct v4l2_subdev *sd)
        if (ret)
                return ret;
 
+       fimc->pipeline_ops = v4l2_get_subdev_hostdata(sd);
+
        ret = fimc_register_capture_device(fimc, sd->v4l2_dev);
-       if (ret)
+       if (ret) {
                fimc_unregister_m2m_device(fimc);
+               fimc->pipeline_ops = NULL;
+       }
 
        return ret;
 }
@@ -1791,6 +1796,7 @@ static void fimc_capture_subdev_unregistered(struct v4l2_subdev *sd)
        if (video_is_registered(&fimc->vid_cap.vfd)) {
                video_unregister_device(&fimc->vid_cap.vfd);
                media_entity_cleanup(&fimc->vid_cap.vfd.entity);
+               fimc->pipeline_ops = NULL;
        }
        kfree(fimc->vid_cap.ctx);
        fimc->vid_cap.ctx = NULL;
index 70bcf39..1b309a7 100644 (file)
@@ -491,8 +491,7 @@ static int fimc_lite_close(struct file *file)
        struct fimc_lite *fimc = video_drvdata(file);
        int ret;
 
-       if (mutex_lock_interruptible(&fimc->lock))
-               return -ERESTARTSYS;
+       mutex_lock(&fimc->lock);
 
        if (--fimc->ref_count == 0 && fimc->out_path == FIMC_IO_DMA) {
                clear_bit(ST_FLITE_IN_USE, &fimc->state);
@@ -1253,7 +1252,9 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd)
        q->buf_struct_size = sizeof(struct flite_buffer);
        q->drv_priv = fimc;
 
-       vb2_queue_init(q);
+       ret = vb2_queue_init(q);
+       if (ret < 0)
+               return ret;
 
        fimc->vd_pad.flags = MEDIA_PAD_FL_SINK;
        ret = media_entity_init(&vfd->entity, 1, &fimc->vd_pad, 0);
@@ -1261,10 +1262,12 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd)
                return ret;
 
        video_set_drvdata(vfd, fimc);
+       fimc->pipeline_ops = v4l2_get_subdev_hostdata(sd);
 
        ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
        if (ret < 0) {
                media_entity_cleanup(&vfd->entity);
+               fimc->pipeline_ops = NULL;
                return ret;
        }
 
@@ -1283,6 +1286,7 @@ static void fimc_lite_subdev_unregistered(struct v4l2_subdev *sd)
        if (video_is_registered(&fimc->vfd)) {
                video_unregister_device(&fimc->vfd);
                media_entity_cleanup(&fimc->vfd.entity);
+               fimc->pipeline_ops = NULL;
        }
 }
 
index 4500e44..62afed3 100644 (file)
@@ -718,8 +718,7 @@ static int fimc_m2m_release(struct file *file)
        dbg("pid: %d, state: 0x%lx, refcnt= %d",
                task_pid_nr(current), fimc->state, fimc->m2m.refcnt);
 
-       if (mutex_lock_interruptible(&fimc->lock))
-               return -ERESTARTSYS;
+       mutex_lock(&fimc->lock);
 
        v4l2_m2m_ctx_release(ctx->m2m_ctx);
        fimc_ctrls_delete(ctx);
index 80ada58..0531ab7 100644 (file)
@@ -343,53 +343,50 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
 static int fimc_register_callback(struct device *dev, void *p)
 {
        struct fimc_dev *fimc = dev_get_drvdata(dev);
-       struct v4l2_subdev *sd = &fimc->vid_cap.subdev;
+       struct v4l2_subdev *sd;
        struct fimc_md *fmd = p;
-       int ret = 0;
-
-       if (!fimc || !fimc->pdev)
-               return 0;
+       int ret;
 
-       if (fimc->pdev->id < 0 || fimc->pdev->id >= FIMC_MAX_DEVS)
+       if (fimc == NULL || fimc->id >= FIMC_MAX_DEVS)
                return 0;
 
-       fimc->pipeline_ops = &fimc_pipeline_ops;
-       fmd->fimc[fimc->pdev->id] = fimc;
+       sd = &fimc->vid_cap.subdev;
        sd->grp_id = FIMC_GROUP_ID;
+       v4l2_set_subdev_hostdata(sd, (void *)&fimc_pipeline_ops);
 
        ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
        if (ret) {
                v4l2_err(&fmd->v4l2_dev, "Failed to register FIMC.%d (%d)\n",
                         fimc->id, ret);
+               return ret;
        }
 
-       return ret;
+       fmd->fimc[fimc->id] = fimc;
+       return 0;
 }
 
 static int fimc_lite_register_callback(struct device *dev, void *p)
 {
        struct fimc_lite *fimc = dev_get_drvdata(dev);
-       struct v4l2_subdev *sd = &fimc->subdev;
        struct fimc_md *fmd = p;
        int ret;
 
-       if (fimc == NULL)
+       if (fimc == NULL || fimc->index >= FIMC_LITE_MAX_DEVS)
                return 0;
 
-       if (fimc->index >= FIMC_LITE_MAX_DEVS)
-               return 0;
-
-       fimc->pipeline_ops = &fimc_pipeline_ops;
-       fmd->fimc_lite[fimc->index] = fimc;
-       sd->grp_id = FLITE_GROUP_ID;
+       fimc->subdev.grp_id = FLITE_GROUP_ID;
+       v4l2_set_subdev_hostdata(&fimc->subdev, (void *)&fimc_pipeline_ops);
 
-       ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
+       ret = v4l2_device_register_subdev(&fmd->v4l2_dev, &fimc->subdev);
        if (ret) {
                v4l2_err(&fmd->v4l2_dev,
                         "Failed to register FIMC-LITE.%d (%d)\n",
                         fimc->index, ret);
+               return ret;
        }
-       return ret;
+
+       fmd->fimc_lite[fimc->index] = fimc;
+       return 0;
 }
 
 static int csis_register_callback(struct device *dev, void *p)
@@ -407,10 +404,12 @@ static int csis_register_callback(struct device *dev, void *p)
        v4l2_info(sd, "csis%d sd: %s\n", pdev->id, sd->name);
 
        id = pdev->id < 0 ? 0 : pdev->id;
-       fmd->csis[id].sd = sd;
        sd->grp_id = CSIS_GROUP_ID;
+
        ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
-       if (ret)
+       if (!ret)
+               fmd->csis[id].sd = sd;
+       else
                v4l2_err(&fmd->v4l2_dev,
                         "Failed to register CSIS subdevice: %d\n", ret);
        return ret;
index 130f4ac..3afe879 100644 (file)
@@ -381,11 +381,8 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
                ctx->consumed_stream += s5p_mfc_hw_call(dev->mfc_ops,
                                                get_consumed_stream, dev);
                if (ctx->codec_mode != S5P_MFC_CODEC_H264_DEC &&
-                       s5p_mfc_hw_call(dev->mfc_ops,
-                               get_dec_frame_type, dev) ==
-                                       S5P_FIMV_DECODE_FRAME_P_FRAME
-                                       && ctx->consumed_stream + STUFF_BYTE <
-                                       src_buf->b->v4l2_planes[0].bytesused) {
+                       ctx->consumed_stream + STUFF_BYTE <
+                       src_buf->b->v4l2_planes[0].bytesused) {
                        /* Run MFC again on the same buffer */
                        mfc_debug(2, "Running again the same buffer\n");
                        ctx->after_packed_pb = 1;
index 50b5bee..3a8cfd9 100644 (file)
@@ -1762,7 +1762,7 @@ int s5p_mfc_get_dspl_y_adr_v6(struct s5p_mfc_dev *dev)
 
 int s5p_mfc_get_dec_y_adr_v6(struct s5p_mfc_dev *dev)
 {
-       return mfc_read(dev, S5P_FIMV_D_DISPLAY_LUMA_ADDR_V6);
+       return mfc_read(dev, S5P_FIMV_D_DECODED_LUMA_ADDR_V6);
 }
 
 int s5p_mfc_get_dspl_status_v6(struct s5p_mfc_dev *dev)
index 85fd312..a1c87f0 100644 (file)
@@ -935,9 +935,10 @@ static int sh_vou_g_crop(struct file *file, void *fh, struct v4l2_crop *a)
 /* Assume a dull encoder, do all the work ourselves. */
 static int sh_vou_s_crop(struct file *file, void *fh, const struct v4l2_crop *a)
 {
+       struct v4l2_crop a_writable = *a;
        struct video_device *vdev = video_devdata(file);
        struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
-       struct v4l2_rect *rect = &a->c;
+       struct v4l2_rect *rect = &a_writable.c;
        struct v4l2_crop sd_crop = {.type = V4L2_BUF_TYPE_VIDEO_OUTPUT};
        struct v4l2_pix_format *pix = &vou_dev->pix;
        struct sh_vou_geometry geo;
index bbe7099..032b8c9 100644 (file)
@@ -470,14 +470,6 @@ static void mx1_camera_remove_device(struct soc_camera_device *icd)
        pcdev->icd = NULL;
 }
 
-static int mx1_camera_set_crop(struct soc_camera_device *icd,
-                              struct v4l2_crop *a)
-{
-       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-
-       return v4l2_subdev_call(sd, video, s_crop, a);
-}
-
 static int mx1_camera_set_bus_param(struct soc_camera_device *icd)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
@@ -689,7 +681,6 @@ static struct soc_camera_host_ops mx1_soc_camera_host_ops = {
        .add            = mx1_camera_add_device,
        .remove         = mx1_camera_remove_device,
        .set_bus_param  = mx1_camera_set_bus_param,
-       .set_crop       = mx1_camera_set_crop,
        .set_fmt        = mx1_camera_set_fmt,
        .try_fmt        = mx1_camera_try_fmt,
        .init_videobuf  = mx1_camera_init_videobuf,
index 9fd9d1c..9a55f4c 100644 (file)
@@ -864,8 +864,10 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count)
 
                bytesperline = soc_mbus_bytes_per_line(icd->user_width,
                                icd->current_fmt->host_fmt);
-               if (bytesperline < 0)
+               if (bytesperline < 0) {
+                       spin_unlock_irqrestore(&pcdev->lock, flags);
                        return bytesperline;
+               }
 
                /*
                 * I didn't manage to properly enable/disable the prp
@@ -878,8 +880,10 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count)
                pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev,
                                pcdev->discard_size, &pcdev->discard_buffer_dma,
                                GFP_KERNEL);
-               if (!pcdev->discard_buffer)
+               if (!pcdev->discard_buffer) {
+                       spin_unlock_irqrestore(&pcdev->lock, flags);
                        return -ENOMEM;
+               }
 
                pcdev->buf_discard[0].discard = true;
                list_add_tail(&pcdev->buf_discard[0].queue,
@@ -1099,9 +1103,10 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd)
 }
 
 static int mx2_camera_set_crop(struct soc_camera_device *icd,
-                               struct v4l2_crop *a)
+                               const struct v4l2_crop *a)
 {
-       struct v4l2_rect *rect = &a->c;
+       struct v4l2_crop a_writable = *a;
+       struct v4l2_rect *rect = &a_writable.c;
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct v4l2_mbus_framefmt mf;
        int ret;
index 3557ac9..261f6e9 100644 (file)
@@ -799,9 +799,10 @@ static inline void stride_align(__u32 *width)
  * default g_crop and cropcap from soc_camera.c
  */
 static int mx3_camera_set_crop(struct soc_camera_device *icd,
-                              struct v4l2_crop *a)
+                              const struct v4l2_crop *a)
 {
-       struct v4l2_rect *rect = &a->c;
+       struct v4l2_crop a_writable = *a;
+       struct v4l2_rect *rect = &a_writable.c;
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx3_camera_dev *mx3_cam = ici->priv;
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
index fa08c76..13636a5 100644 (file)
@@ -1215,9 +1215,9 @@ static int set_mbus_format(struct omap1_cam_dev *pcdev, struct device *dev,
 }
 
 static int omap1_cam_set_crop(struct soc_camera_device *icd,
-                              struct v4l2_crop *crop)
+                              const struct v4l2_crop *crop)
 {
-       struct v4l2_rect *rect = &crop->c;
+       const struct v4l2_rect *rect = &crop->c;
        const struct soc_camera_format_xlate *xlate = icd->current_fmt;
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct device *dev = icd->parent;
index 1e3776d..3434ffe 100644 (file)
@@ -1337,9 +1337,9 @@ static int pxa_camera_check_frame(u32 width, u32 height)
 }
 
 static int pxa_camera_set_crop(struct soc_camera_device *icd,
-                              struct v4l2_crop *a)
+                              const struct v4l2_crop *a)
 {
-       struct v4l2_rect *rect = &a->c;
+       const struct v4l2_rect *rect = &a->c;
        struct device *dev = icd->parent;
        struct soc_camera_host *ici = to_soc_camera_host(dev);
        struct pxa_camera_dev *pcdev = ici->priv;
index 0a24253..2d8861c 100644 (file)
@@ -1182,13 +1182,13 @@ static void sh_mobile_ceu_put_formats(struct soc_camera_device *icd)
 }
 
 /* Check if any dimension of r1 is smaller than respective one of r2 */
-static bool is_smaller(struct v4l2_rect *r1, struct v4l2_rect *r2)
+static bool is_smaller(const struct v4l2_rect *r1, const struct v4l2_rect *r2)
 {
        return r1->width < r2->width || r1->height < r2->height;
 }
 
 /* Check if r1 fails to cover r2 */
-static bool is_inside(struct v4l2_rect *r1, struct v4l2_rect *r2)
+static bool is_inside(const struct v4l2_rect *r1, const struct v4l2_rect *r2)
 {
        return r1->left > r2->left || r1->top > r2->top ||
                r1->left + r1->width < r2->left + r2->width ||
@@ -1263,7 +1263,7 @@ static void update_subrect(struct sh_mobile_ceu_cam *cam)
  * 3. if (2) failed, try to request the maximum image
  */
 static int client_s_crop(struct soc_camera_device *icd, struct v4l2_crop *crop,
-                        const struct v4l2_crop *cam_crop)
+                        struct v4l2_crop *cam_crop)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct v4l2_rect *rect = &crop->c, *cam_rect = &cam_crop->c;
@@ -1519,7 +1519,8 @@ static int client_scale(struct soc_camera_device *icd,
 static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
                                  const struct v4l2_crop *a)
 {
-       struct v4l2_rect *rect = &a->c;
+       struct v4l2_crop a_writable = *a;
+       const struct v4l2_rect *rect = &a_writable.c;
        struct device *dev = icd->parent;
        struct soc_camera_host *ici = to_soc_camera_host(dev);
        struct sh_mobile_ceu_dev *pcdev = ici->priv;
@@ -1545,7 +1546,7 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
         * 1. - 2. Apply iterative camera S_CROP for new input window, read back
         * actual camera rectangle.
         */
-       ret = client_s_crop(icd, a, &cam_crop);
+       ret = client_s_crop(icd, &a_writable, &cam_crop);
        if (ret < 0)
                return ret;
 
@@ -1946,7 +1947,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
 }
 
 static int sh_mobile_ceu_set_livecrop(struct soc_camera_device *icd,
-                                     struct v4l2_crop *a)
+                                     const struct v4l2_crop *a)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
index 9859d2a..ba51f65 100644 (file)
@@ -283,14 +283,13 @@ static inline int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed,
 
        /* activate the pid on the device pid filter */
        if (adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER &&
-                       adap->pid_filtering &&
-                       adap->props->pid_filter)
+                       adap->pid_filtering && adap->props->pid_filter) {
                ret = adap->props->pid_filter(adap, dvbdmxfeed->index,
                                dvbdmxfeed->pid, (count == 1) ? 1 : 0);
-                       if (ret < 0)
-                               dev_err(&d->udev->dev, "%s: pid_filter() " \
-                                               "failed=%d\n", KBUILD_MODNAME,
-                                               ret);
+               if (ret < 0)
+                       dev_err(&d->udev->dev, "%s: pid_filter() failed=%d\n",
+                                       KBUILD_MODNAME, ret);
+       }
 
        /* start feeding if it is first pid */
        if (adap->feed_count == 1 && count == 1) {
index 0431bee..5716662 100644 (file)
@@ -32,9 +32,7 @@ int dvb_usbv2_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf,
                return -EINVAL;
        }
 
-       ret = mutex_lock_interruptible(&d->usb_mutex);
-       if (ret < 0)
-               return ret;
+       mutex_lock(&d->usb_mutex);
 
        dev_dbg(&d->udev->dev, "%s: >>> %*ph\n", __func__, wlen, wbuf);
 
index adabba8..093f1ac 100644 (file)
@@ -1346,6 +1346,10 @@ static const struct usb_device_id rtl28xxu_id_table[] = {
                &rtl2832u_props, "DigitalNow Quad DVB-T Receiver", NULL) },
        { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d3,
                &rtl2832u_props, "TerraTec Cinergy T Stick RC (Rev. 3)", NULL) },
+       { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1102,
+               &rtl2832u_props, "Dexatek DK mini DVB-T Dongle", NULL) },
+       { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d7,
+               &rtl2832u_props, "TerraTec Cinergy T Stick+", NULL) },
        { }
 };
 MODULE_DEVICE_TABLE(usb, rtl28xxu_id_table);
index 1b48f20..f4f9bf8 100644 (file)
@@ -98,9 +98,9 @@ static irqreturn_t arizona_underclocked(int irq, void *data)
 
        if (val & ARIZONA_AIF3_UNDERCLOCKED_STS)
                dev_err(arizona->dev, "AIF3 underclocked\n");
-       if (val & ARIZONA_AIF3_UNDERCLOCKED_STS)
-               dev_err(arizona->dev, "AIF3 underclocked\n");
        if (val & ARIZONA_AIF2_UNDERCLOCKED_STS)
+               dev_err(arizona->dev, "AIF2 underclocked\n");
+       if (val & ARIZONA_AIF1_UNDERCLOCKED_STS)
                dev_err(arizona->dev, "AIF1 underclocked\n");
        if (val & ARIZONA_ISRC2_UNDERCLOCKED_STS)
                dev_err(arizona->dev, "ISRC2 underclocked\n");
@@ -415,11 +415,19 @@ int __devinit arizona_dev_init(struct arizona *arizona)
 
        /* If we have a /RESET GPIO we'll already be reset */
        if (!arizona->pdata.reset) {
+               regcache_mark_dirty(arizona->regmap);
+
                ret = regmap_write(arizona->regmap, ARIZONA_SOFTWARE_RESET, 0);
                if (ret != 0) {
                        dev_err(dev, "Failed to reset device: %d\n", ret);
                        goto err_reset;
                }
+
+               ret = regcache_sync(arizona->regmap);
+               if (ret != 0) {
+                       dev_err(dev, "Failed to sync device: %d\n", ret);
+                       goto err_reset;
+               }
        }
 
        ret = arizona_wait_for_boot(arizona);
@@ -520,7 +528,7 @@ int __devinit arizona_dev_init(struct arizona *arizona)
                break;
        case WM5110:
                ret = mfd_add_devices(arizona->dev, -1, wm5110_devs,
-                                     ARRAY_SIZE(wm5102_devs), NULL, 0, NULL);
+                                     ARRAY_SIZE(wm5110_devs), NULL, 0, NULL);
                break;
        }
 
index ef0f2d0..b1b0091 100644 (file)
@@ -178,6 +178,7 @@ int arizona_irq_init(struct arizona *arizona)
 
                switch (arizona->rev) {
                case 0:
+               case 1:
                        ctrlif_error = false;
                        break;
                default:
index 00b8b0f..b96661d 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/mfd/abx500/ab8500.h>
 #include <linux/regulator/db8500-prcmu.h>
 #include <linux/regulator/machine.h>
+#include <linux/cpufreq.h>
 #include <asm/hardware/gic.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
@@ -420,9 +421,6 @@ static struct {
 
 static atomic_t ac_wake_req_state = ATOMIC_INIT(0);
 
-/* Functions definition */
-static void compute_armss_rate(void);
-
 /* Spinlocks */
 static DEFINE_SPINLOCK(prcmu_lock);
 static DEFINE_SPINLOCK(clkout_lock);
@@ -1019,7 +1017,6 @@ int db8500_prcmu_set_arm_opp(u8 opp)
                (mb1_transfer.ack.arm_opp != opp))
                r = -EIO;
 
-       compute_armss_rate();
        mutex_unlock(&mb1_transfer.lock);
 
        return r;
@@ -1169,12 +1166,12 @@ int db8500_prcmu_get_ape_opp(void)
 }
 
 /**
- * prcmu_request_ape_opp_100_voltage - Request APE OPP 100% voltage
+ * db8500_prcmu_request_ape_opp_100_voltage - Request APE OPP 100% voltage
  * @enable: true to request the higher voltage, false to drop a request.
  *
  * Calls to this function to enable and disable requests must be balanced.
  */
-int prcmu_request_ape_opp_100_voltage(bool enable)
+int db8500_prcmu_request_ape_opp_100_voltage(bool enable)
 {
        int r = 0;
        u8 header;
@@ -1669,13 +1666,8 @@ static unsigned long clock_rate(u8 clock)
        else
                return 0;
 }
-static unsigned long latest_armss_rate;
-static unsigned long armss_rate(void)
-{
-       return latest_armss_rate;
-}
 
-static void compute_armss_rate(void)
+static unsigned long armss_rate(void)
 {
        u32 r;
        unsigned long rate;
@@ -1700,7 +1692,7 @@ static void compute_armss_rate(void)
                rate = pll_rate(PRCM_PLLARM_FREQ, ROOT_CLOCK_RATE, PLL_DIV);
        }
 
-       latest_armss_rate = rate;
+       return rate;
 }
 
 static unsigned long dsiclk_rate(u8 n)
@@ -1820,6 +1812,35 @@ static long round_clock_rate(u8 clock, unsigned long rate)
        return rounded_rate;
 }
 
+/* CPU FREQ table, may be changed due to if MAX_OPP is supported. */
+static struct cpufreq_frequency_table db8500_cpufreq_table[] = {
+       { .frequency = 200000, .index = ARM_EXTCLK,},
+       { .frequency = 400000, .index = ARM_50_OPP,},
+       { .frequency = 800000, .index = ARM_100_OPP,},
+       { .frequency = CPUFREQ_TABLE_END,}, /* To be used for MAX_OPP. */
+       { .frequency = CPUFREQ_TABLE_END,},
+};
+
+static long round_armss_rate(unsigned long rate)
+{
+       long freq = 0;
+       int i = 0;
+
+       /* cpufreq table frequencies is in KHz. */
+       rate = rate / 1000;
+
+       /* Find the corresponding arm opp from the cpufreq table. */
+       while (db8500_cpufreq_table[i].frequency != CPUFREQ_TABLE_END) {
+               freq = db8500_cpufreq_table[i].frequency;
+               if (freq == rate)
+                       break;
+               i++;
+       }
+
+       /* Return the last valid value, even if a match was not found. */
+       return freq * 1000;
+}
+
 #define MIN_PLL_VCO_RATE 600000000ULL
 #define MAX_PLL_VCO_RATE 1680640000ULL
 
@@ -1891,6 +1912,8 @@ long prcmu_round_clock_rate(u8 clock, unsigned long rate)
 {
        if (clock < PRCMU_NUM_REG_CLOCKS)
                return round_clock_rate(clock, rate);
+       else if (clock == PRCMU_ARMSS)
+               return round_armss_rate(rate);
        else if (clock == PRCMU_PLLDSI)
                return round_plldsi_rate(rate);
        else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
@@ -1950,6 +1973,27 @@ static void set_clock_rate(u8 clock, unsigned long rate)
        spin_unlock_irqrestore(&clk_mgt_lock, flags);
 }
 
+static int set_armss_rate(unsigned long rate)
+{
+       int i = 0;
+
+       /* cpufreq table frequencies is in KHz. */
+       rate = rate / 1000;
+
+       /* Find the corresponding arm opp from the cpufreq table. */
+       while (db8500_cpufreq_table[i].frequency != CPUFREQ_TABLE_END) {
+               if (db8500_cpufreq_table[i].frequency == rate)
+                       break;
+               i++;
+       }
+
+       if (db8500_cpufreq_table[i].frequency != rate)
+               return -EINVAL;
+
+       /* Set the new arm opp. */
+       return db8500_prcmu_set_arm_opp(db8500_cpufreq_table[i].index);
+}
+
 static int set_plldsi_rate(unsigned long rate)
 {
        unsigned long src_rate;
@@ -2030,6 +2074,8 @@ int prcmu_set_clock_rate(u8 clock, unsigned long rate)
 {
        if (clock < PRCMU_NUM_REG_CLOCKS)
                set_clock_rate(clock, rate);
+       else if (clock == PRCMU_ARMSS)
+               return set_armss_rate(rate);
        else if (clock == PRCMU_PLLDSI)
                return set_plldsi_rate(rate);
        else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
@@ -2754,8 +2800,6 @@ void __init db8500_prcmu_early_init(void)
        init_completion(&mb5_transfer.work);
 
        INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work);
-
-       compute_armss_rate();
 }
 
 static void __init init_prcm_registers(void)
@@ -3020,6 +3064,8 @@ static struct mfd_cell db8500_prcmu_devs[] = {
        {
                .name = "cpufreq-u8500",
                .of_compatible = "stericsson,cpufreq-u8500",
+               .platform_data = &db8500_cpufreq_table,
+               .pdata_size = sizeof(db8500_cpufreq_table),
        },
        {
                .name = "ab8500-core",
@@ -3030,6 +3076,14 @@ static struct mfd_cell db8500_prcmu_devs[] = {
        },
 };
 
+static void db8500_prcmu_update_cpufreq(void)
+{
+       if (prcmu_has_arm_maxopp()) {
+               db8500_cpufreq_table[3].frequency = 1000000;
+               db8500_cpufreq_table[3].index = ARM_MAX_OPP;
+       }
+}
+
 /**
  * prcmu_fw_init - arch init call for the Linux PRCMU fw init logic
  *
@@ -3074,6 +3128,8 @@ static int __devinit db8500_prcmu_probe(struct platform_device *pdev)
        if (cpu_is_u8500v20_or_later())
                prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);
 
+       db8500_prcmu_update_cpufreq();
+
        err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs,
                              ARRAY_SIZE(db8500_prcmu_devs), NULL, 0, NULL);
        if (err) {
index 4ae6423..a071a86 100644 (file)
@@ -671,7 +671,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
        }
 
        if (IS_ENABLED(CONFIG_PWM_TWL6030) && twl_class_is_6030()) {
-               child = add_child(TWL6030_MODULE_ID1, "twl6030-pwm", NULL, 0,
+               child = add_child(SUB_CHIP_ID1, "twl6030-pwm", NULL, 0,
                                  false, 0, 0);
                if (IS_ERR(child))
                        return PTR_ERR(child);
index ad733d7..cdd1173 100644 (file)
@@ -672,7 +672,8 @@ int twl4030_sih_setup(struct device *dev, int module, int irq_base)
        irq = sih_mod + twl4030_irq_base;
        irq_set_handler_data(irq, agent);
        agent->irq_name = kasprintf(GFP_KERNEL, "twl4030_%s", sih->name);
-       status = request_threaded_irq(irq, NULL, handle_twl4030_sih, 0,
+       status = request_threaded_irq(irq, NULL, handle_twl4030_sih,
+                                     IRQF_EARLY_RESUME,
                                      agent->irq_name ?: sih->name, NULL);
 
        dev_info(dev, "%s (irq %d) chaining IRQs %d..%d\n", sih->name,
index 01b9255..14490cc 100644 (file)
@@ -43,6 +43,7 @@ static const struct reg_default wm5102_reva_patch[] = {
        { 0x479, 0x0A30 },
        { 0x47B, 0x0810 },
        { 0x47D, 0x0510 },
+       { 0x4D1, 0x017F },
        { 0x500, 0x000D },
        { 0x507, 0x1820 },
        { 0x508, 0x1820 },
@@ -52,524 +53,6 @@ static const struct reg_default wm5102_reva_patch[] = {
        { 0x580, 0x000D },
        { 0x587, 0x1820 },
        { 0x588, 0x1820 },
-       { 0x101, 0x8140 },
-       { 0x3000, 0x2225 },
-       { 0x3001, 0x3a03 },
-       { 0x3002, 0x0225 },
-       { 0x3003, 0x0801 },
-       { 0x3004, 0x6249 },
-       { 0x3005, 0x0c04 },
-       { 0x3006, 0x0225 },
-       { 0x3007, 0x5901 },
-       { 0x3008, 0xe249 },
-       { 0x3009, 0x030d },
-       { 0x300a, 0x0249 },
-       { 0x300b, 0x2c01 },
-       { 0x300c, 0xe249 },
-       { 0x300d, 0x4342 },
-       { 0x300e, 0xe249 },
-       { 0x300f, 0x73c0 },
-       { 0x3010, 0x4249 },
-       { 0x3011, 0x0c00 },
-       { 0x3012, 0x0225 },
-       { 0x3013, 0x1f01 },
-       { 0x3014, 0x0225 },
-       { 0x3015, 0x1e01 },
-       { 0x3016, 0x0225 },
-       { 0x3017, 0xfa00 },
-       { 0x3018, 0x0000 },
-       { 0x3019, 0xf000 },
-       { 0x301a, 0x0000 },
-       { 0x301b, 0xf000 },
-       { 0x301c, 0x0000 },
-       { 0x301d, 0xf000 },
-       { 0x301e, 0x0000 },
-       { 0x301f, 0xf000 },
-       { 0x3020, 0x0000 },
-       { 0x3021, 0xf000 },
-       { 0x3022, 0x0000 },
-       { 0x3023, 0xf000 },
-       { 0x3024, 0x0000 },
-       { 0x3025, 0xf000 },
-       { 0x3026, 0x0000 },
-       { 0x3027, 0xf000 },
-       { 0x3028, 0x0000 },
-       { 0x3029, 0xf000 },
-       { 0x302a, 0x0000 },
-       { 0x302b, 0xf000 },
-       { 0x302c, 0x0000 },
-       { 0x302d, 0xf000 },
-       { 0x302e, 0x0000 },
-       { 0x302f, 0xf000 },
-       { 0x3030, 0x0225 },
-       { 0x3031, 0x1a01 },
-       { 0x3032, 0x0225 },
-       { 0x3033, 0x1e00 },
-       { 0x3034, 0x0225 },
-       { 0x3035, 0x1f00 },
-       { 0x3036, 0x6225 },
-       { 0x3037, 0xf800 },
-       { 0x3038, 0x0000 },
-       { 0x3039, 0xf000 },
-       { 0x303a, 0x0000 },
-       { 0x303b, 0xf000 },
-       { 0x303c, 0x0000 },
-       { 0x303d, 0xf000 },
-       { 0x303e, 0x0000 },
-       { 0x303f, 0xf000 },
-       { 0x3040, 0x2226 },
-       { 0x3041, 0x3a03 },
-       { 0x3042, 0x0226 },
-       { 0x3043, 0x0801 },
-       { 0x3044, 0x6249 },
-       { 0x3045, 0x0c06 },
-       { 0x3046, 0x0226 },
-       { 0x3047, 0x5901 },
-       { 0x3048, 0xe249 },
-       { 0x3049, 0x030d },
-       { 0x304a, 0x0249 },
-       { 0x304b, 0x2c01 },
-       { 0x304c, 0xe249 },
-       { 0x304d, 0x4342 },
-       { 0x304e, 0xe249 },
-       { 0x304f, 0x73c0 },
-       { 0x3050, 0x4249 },
-       { 0x3051, 0x0c00 },
-       { 0x3052, 0x0226 },
-       { 0x3053, 0x1f01 },
-       { 0x3054, 0x0226 },
-       { 0x3055, 0x1e01 },
-       { 0x3056, 0x0226 },
-       { 0x3057, 0xfa00 },
-       { 0x3058, 0x0000 },
-       { 0x3059, 0xf000 },
-       { 0x305a, 0x0000 },
-       { 0x305b, 0xf000 },
-       { 0x305c, 0x0000 },
-       { 0x305d, 0xf000 },
-       { 0x305e, 0x0000 },
-       { 0x305f, 0xf000 },
-       { 0x3060, 0x0000 },
-       { 0x3061, 0xf000 },
-       { 0x3062, 0x0000 },
-       { 0x3063, 0xf000 },
-       { 0x3064, 0x0000 },
-       { 0x3065, 0xf000 },
-       { 0x3066, 0x0000 },
-       { 0x3067, 0xf000 },
-       { 0x3068, 0x0000 },
-       { 0x3069, 0xf000 },
-       { 0x306a, 0x0000 },
-       { 0x306b, 0xf000 },
-       { 0x306c, 0x0000 },
-       { 0x306d, 0xf000 },
-       { 0x306e, 0x0000 },
-       { 0x306f, 0xf000 },
-       { 0x3070, 0x0226 },
-       { 0x3071, 0x1a01 },
-       { 0x3072, 0x0226 },
-       { 0x3073, 0x1e00 },
-       { 0x3074, 0x0226 },
-       { 0x3075, 0x1f00 },
-       { 0x3076, 0x6226 },
-       { 0x3077, 0xf800 },
-       { 0x3078, 0x0000 },
-       { 0x3079, 0xf000 },
-       { 0x307a, 0x0000 },
-       { 0x307b, 0xf000 },
-       { 0x307c, 0x0000 },
-       { 0x307d, 0xf000 },
-       { 0x307e, 0x0000 },
-       { 0x307f, 0xf000 },
-       { 0x3080, 0x2227 },
-       { 0x3081, 0x3a03 },
-       { 0x3082, 0x0227 },
-       { 0x3083, 0x0801 },
-       { 0x3084, 0x6255 },
-       { 0x3085, 0x0c04 },
-       { 0x3086, 0x0227 },
-       { 0x3087, 0x5901 },
-       { 0x3088, 0xe255 },
-       { 0x3089, 0x030d },
-       { 0x308a, 0x0255 },
-       { 0x308b, 0x2c01 },
-       { 0x308c, 0xe255 },
-       { 0x308d, 0x4342 },
-       { 0x308e, 0xe255 },
-       { 0x308f, 0x73c0 },
-       { 0x3090, 0x4255 },
-       { 0x3091, 0x0c00 },
-       { 0x3092, 0x0227 },
-       { 0x3093, 0x1f01 },
-       { 0x3094, 0x0227 },
-       { 0x3095, 0x1e01 },
-       { 0x3096, 0x0227 },
-       { 0x3097, 0xfa00 },
-       { 0x3098, 0x0000 },
-       { 0x3099, 0xf000 },
-       { 0x309a, 0x0000 },
-       { 0x309b, 0xf000 },
-       { 0x309c, 0x0000 },
-       { 0x309d, 0xf000 },
-       { 0x309e, 0x0000 },
-       { 0x309f, 0xf000 },
-       { 0x30a0, 0x0000 },
-       { 0x30a1, 0xf000 },
-       { 0x30a2, 0x0000 },
-       { 0x30a3, 0xf000 },
-       { 0x30a4, 0x0000 },
-       { 0x30a5, 0xf000 },
-       { 0x30a6, 0x0000 },
-       { 0x30a7, 0xf000 },
-       { 0x30a8, 0x0000 },
-       { 0x30a9, 0xf000 },
-       { 0x30aa, 0x0000 },
-       { 0x30ab, 0xf000 },
-       { 0x30ac, 0x0000 },
-       { 0x30ad, 0xf000 },
-       { 0x30ae, 0x0000 },
-       { 0x30af, 0xf000 },
-       { 0x30b0, 0x0227 },
-       { 0x30b1, 0x1a01 },
-       { 0x30b2, 0x0227 },
-       { 0x30b3, 0x1e00 },
-       { 0x30b4, 0x0227 },
-       { 0x30b5, 0x1f00 },
-       { 0x30b6, 0x6227 },
-       { 0x30b7, 0xf800 },
-       { 0x30b8, 0x0000 },
-       { 0x30b9, 0xf000 },
-       { 0x30ba, 0x0000 },
-       { 0x30bb, 0xf000 },
-       { 0x30bc, 0x0000 },
-       { 0x30bd, 0xf000 },
-       { 0x30be, 0x0000 },
-       { 0x30bf, 0xf000 },
-       { 0x30c0, 0x2228 },
-       { 0x30c1, 0x3a03 },
-       { 0x30c2, 0x0228 },
-       { 0x30c3, 0x0801 },
-       { 0x30c4, 0x6255 },
-       { 0x30c5, 0x0c06 },
-       { 0x30c6, 0x0228 },
-       { 0x30c7, 0x5901 },
-       { 0x30c8, 0xe255 },
-       { 0x30c9, 0x030d },
-       { 0x30ca, 0x0255 },
-       { 0x30cb, 0x2c01 },
-       { 0x30cc, 0xe255 },
-       { 0x30cd, 0x4342 },
-       { 0x30ce, 0xe255 },
-       { 0x30cf, 0x73c0 },
-       { 0x30d0, 0x4255 },
-       { 0x30d1, 0x0c00 },
-       { 0x30d2, 0x0228 },
-       { 0x30d3, 0x1f01 },
-       { 0x30d4, 0x0228 },
-       { 0x30d5, 0x1e01 },
-       { 0x30d6, 0x0228 },
-       { 0x30d7, 0xfa00 },
-       { 0x30d8, 0x0000 },
-       { 0x30d9, 0xf000 },
-       { 0x30da, 0x0000 },
-       { 0x30db, 0xf000 },
-       { 0x30dc, 0x0000 },
-       { 0x30dd, 0xf000 },
-       { 0x30de, 0x0000 },
-       { 0x30df, 0xf000 },
-       { 0x30e0, 0x0000 },
-       { 0x30e1, 0xf000 },
-       { 0x30e2, 0x0000 },
-       { 0x30e3, 0xf000 },
-       { 0x30e4, 0x0000 },
-       { 0x30e5, 0xf000 },
-       { 0x30e6, 0x0000 },
-       { 0x30e7, 0xf000 },
-       { 0x30e8, 0x0000 },
-       { 0x30e9, 0xf000 },
-       { 0x30ea, 0x0000 },
-       { 0x30eb, 0xf000 },
-       { 0x30ec, 0x0000 },
-       { 0x30ed, 0xf000 },
-       { 0x30ee, 0x0000 },
-       { 0x30ef, 0xf000 },
-       { 0x30f0, 0x0228 },
-       { 0x30f1, 0x1a01 },
-       { 0x30f2, 0x0228 },
-       { 0x30f3, 0x1e00 },
-       { 0x30f4, 0x0228 },
-       { 0x30f5, 0x1f00 },
-       { 0x30f6, 0x6228 },
-       { 0x30f7, 0xf800 },
-       { 0x30f8, 0x0000 },
-       { 0x30f9, 0xf000 },
-       { 0x30fa, 0x0000 },
-       { 0x30fb, 0xf000 },
-       { 0x30fc, 0x0000 },
-       { 0x30fd, 0xf000 },
-       { 0x30fe, 0x0000 },
-       { 0x30ff, 0xf000 },
-       { 0x3100, 0x222b },
-       { 0x3101, 0x3a03 },
-       { 0x3102, 0x222b },
-       { 0x3103, 0x5803 },
-       { 0x3104, 0xe26f },
-       { 0x3105, 0x030d },
-       { 0x3106, 0x626f },
-       { 0x3107, 0x2c01 },
-       { 0x3108, 0xe26f },
-       { 0x3109, 0x4342 },
-       { 0x310a, 0xe26f },
-       { 0x310b, 0x73c0 },
-       { 0x310c, 0x026f },
-       { 0x310d, 0x0c00 },
-       { 0x310e, 0x022b },
-       { 0x310f, 0x1f01 },
-       { 0x3110, 0x022b },
-       { 0x3111, 0x1e01 },
-       { 0x3112, 0x022b },
-       { 0x3113, 0xfa00 },
-       { 0x3114, 0x0000 },
-       { 0x3115, 0xf000 },
-       { 0x3116, 0x0000 },
-       { 0x3117, 0xf000 },
-       { 0x3118, 0x0000 },
-       { 0x3119, 0xf000 },
-       { 0x311a, 0x0000 },
-       { 0x311b, 0xf000 },
-       { 0x311c, 0x0000 },
-       { 0x311d, 0xf000 },
-       { 0x311e, 0x0000 },
-       { 0x311f, 0xf000 },
-       { 0x3120, 0x022b },
-       { 0x3121, 0x0a01 },
-       { 0x3122, 0x022b },
-       { 0x3123, 0x1e00 },
-       { 0x3124, 0x022b },
-       { 0x3125, 0x1f00 },
-       { 0x3126, 0x622b },
-       { 0x3127, 0xf800 },
-       { 0x3128, 0x0000 },
-       { 0x3129, 0xf000 },
-       { 0x312a, 0x0000 },
-       { 0x312b, 0xf000 },
-       { 0x312c, 0x0000 },
-       { 0x312d, 0xf000 },
-       { 0x312e, 0x0000 },
-       { 0x312f, 0xf000 },
-       { 0x3130, 0x0000 },
-       { 0x3131, 0xf000 },
-       { 0x3132, 0x0000 },
-       { 0x3133, 0xf000 },
-       { 0x3134, 0x0000 },
-       { 0x3135, 0xf000 },
-       { 0x3136, 0x0000 },
-       { 0x3137, 0xf000 },
-       { 0x3138, 0x0000 },
-       { 0x3139, 0xf000 },
-       { 0x313a, 0x0000 },
-       { 0x313b, 0xf000 },
-       { 0x313c, 0x0000 },
-       { 0x313d, 0xf000 },
-       { 0x313e, 0x0000 },
-       { 0x313f, 0xf000 },
-       { 0x3140, 0x0000 },
-       { 0x3141, 0xf000 },
-       { 0x3142, 0x0000 },
-       { 0x3143, 0xf000 },
-       { 0x3144, 0x0000 },
-       { 0x3145, 0xf000 },
-       { 0x3146, 0x0000 },
-       { 0x3147, 0xf000 },
-       { 0x3148, 0x0000 },
-       { 0x3149, 0xf000 },
-       { 0x314a, 0x0000 },
-       { 0x314b, 0xf000 },
-       { 0x314c, 0x0000 },
-       { 0x314d, 0xf000 },
-       { 0x314e, 0x0000 },
-       { 0x314f, 0xf000 },
-       { 0x3150, 0x0000 },
-       { 0x3151, 0xf000 },
-       { 0x3152, 0x0000 },
-       { 0x3153, 0xf000 },
-       { 0x3154, 0x0000 },
-       { 0x3155, 0xf000 },
-       { 0x3156, 0x0000 },
-       { 0x3157, 0xf000 },
-       { 0x3158, 0x0000 },
-       { 0x3159, 0xf000 },
-       { 0x315a, 0x0000 },
-       { 0x315b, 0xf000 },
-       { 0x315c, 0x0000 },
-       { 0x315d, 0xf000 },
-       { 0x315e, 0x0000 },
-       { 0x315f, 0xf000 },
-       { 0x3160, 0x0000 },
-       { 0x3161, 0xf000 },
-       { 0x3162, 0x0000 },
-       { 0x3163, 0xf000 },
-       { 0x3164, 0x0000 },
-       { 0x3165, 0xf000 },
-       { 0x3166, 0x0000 },
-       { 0x3167, 0xf000 },
-       { 0x3168, 0x0000 },
-       { 0x3169, 0xf000 },
-       { 0x316a, 0x0000 },
-       { 0x316b, 0xf000 },
-       { 0x316c, 0x0000 },
-       { 0x316d, 0xf000 },
-       { 0x316e, 0x0000 },
-       { 0x316f, 0xf000 },
-       { 0x3170, 0x0000 },
-       { 0x3171, 0xf000 },
-       { 0x3172, 0x0000 },
-       { 0x3173, 0xf000 },
-       { 0x3174, 0x0000 },
-       { 0x3175, 0xf000 },
-       { 0x3176, 0x0000 },
-       { 0x3177, 0xf000 },
-       { 0x3178, 0x0000 },
-       { 0x3179, 0xf000 },
-       { 0x317a, 0x0000 },
-       { 0x317b, 0xf000 },
-       { 0x317c, 0x0000 },
-       { 0x317d, 0xf000 },
-       { 0x317e, 0x0000 },
-       { 0x317f, 0xf000 },
-       { 0x3180, 0x2001 },
-       { 0x3181, 0xf101 },
-       { 0x3182, 0x0000 },
-       { 0x3183, 0xf000 },
-       { 0x3184, 0x0000 },
-       { 0x3185, 0xf000 },
-       { 0x3186, 0x0000 },
-       { 0x3187, 0xf000 },
-       { 0x3188, 0x0000 },
-       { 0x3189, 0xf000 },
-       { 0x318a, 0x0000 },
-       { 0x318b, 0xf000 },
-       { 0x318c, 0x0000 },
-       { 0x318d, 0xf000 },
-       { 0x318e, 0x0000 },
-       { 0x318f, 0xf000 },
-       { 0x3190, 0x0000 },
-       { 0x3191, 0xf000 },
-       { 0x3192, 0x0000 },
-       { 0x3193, 0xf000 },
-       { 0x3194, 0x0000 },
-       { 0x3195, 0xf000 },
-       { 0x3196, 0x0000 },
-       { 0x3197, 0xf000 },
-       { 0x3198, 0x0000 },
-       { 0x3199, 0xf000 },
-       { 0x319a, 0x0000 },
-       { 0x319b, 0xf000 },
-       { 0x319c, 0x0000 },
-       { 0x319d, 0xf000 },
-       { 0x319e, 0x0000 },
-       { 0x319f, 0xf000 },
-       { 0x31a0, 0x0000 },
-       { 0x31a1, 0xf000 },
-       { 0x31a2, 0x0000 },
-       { 0x31a3, 0xf000 },
-       { 0x31a4, 0x0000 },
-       { 0x31a5, 0xf000 },
-       { 0x31a6, 0x0000 },
-       { 0x31a7, 0xf000 },
-       { 0x31a8, 0x0000 },
-       { 0x31a9, 0xf000 },
-       { 0x31aa, 0x0000 },
-       { 0x31ab, 0xf000 },
-       { 0x31ac, 0x0000 },
-       { 0x31ad, 0xf000 },
-       { 0x31ae, 0x0000 },
-       { 0x31af, 0xf000 },
-       { 0x31b0, 0x0000 },
-       { 0x31b1, 0xf000 },
-       { 0x31b2, 0x0000 },
-       { 0x31b3, 0xf000 },
-       { 0x31b4, 0x0000 },
-       { 0x31b5, 0xf000 },
-       { 0x31b6, 0x0000 },
-       { 0x31b7, 0xf000 },
-       { 0x31b8, 0x0000 },
-       { 0x31b9, 0xf000 },
-       { 0x31ba, 0x0000 },
-       { 0x31bb, 0xf000 },
-       { 0x31bc, 0x0000 },
-       { 0x31bd, 0xf000 },
-       { 0x31be, 0x0000 },
-       { 0x31bf, 0xf000 },
-       { 0x31c0, 0x0000 },
-       { 0x31c1, 0xf000 },
-       { 0x31c2, 0x0000 },
-       { 0x31c3, 0xf000 },
-       { 0x31c4, 0x0000 },
-       { 0x31c5, 0xf000 },
-       { 0x31c6, 0x0000 },
-       { 0x31c7, 0xf000 },
-       { 0x31c8, 0x0000 },
-       { 0x31c9, 0xf000 },
-       { 0x31ca, 0x0000 },
-       { 0x31cb, 0xf000 },
-       { 0x31cc, 0x0000 },
-       { 0x31cd, 0xf000 },
-       { 0x31ce, 0x0000 },
-       { 0x31cf, 0xf000 },
-       { 0x31d0, 0x0000 },
-       { 0x31d1, 0xf000 },
-       { 0x31d2, 0x0000 },
-       { 0x31d3, 0xf000 },
-       { 0x31d4, 0x0000 },
-       { 0x31d5, 0xf000 },
-       { 0x31d6, 0x0000 },
-       { 0x31d7, 0xf000 },
-       { 0x31d8, 0x0000 },
-       { 0x31d9, 0xf000 },
-       { 0x31da, 0x0000 },
-       { 0x31db, 0xf000 },
-       { 0x31dc, 0x0000 },
-       { 0x31dd, 0xf000 },
-       { 0x31de, 0x0000 },
-       { 0x31df, 0xf000 },
-       { 0x31e0, 0x0000 },
-       { 0x31e1, 0xf000 },
-       { 0x31e2, 0x0000 },
-       { 0x31e3, 0xf000 },
-       { 0x31e4, 0x0000 },
-       { 0x31e5, 0xf000 },
-       { 0x31e6, 0x0000 },
-       { 0x31e7, 0xf000 },
-       { 0x31e8, 0x0000 },
-       { 0x31e9, 0xf000 },
-       { 0x31ea, 0x0000 },
-       { 0x31eb, 0xf000 },
-       { 0x31ec, 0x0000 },
-       { 0x31ed, 0xf000 },
-       { 0x31ee, 0x0000 },
-       { 0x31ef, 0xf000 },
-       { 0x31f0, 0x0000 },
-       { 0x31f1, 0xf000 },
-       { 0x31f2, 0x0000 },
-       { 0x31f3, 0xf000 },
-       { 0x31f4, 0x0000 },
-       { 0x31f5, 0xf000 },
-       { 0x31f6, 0x0000 },
-       { 0x31f7, 0xf000 },
-       { 0x31f8, 0x0000 },
-       { 0x31f9, 0xf000 },
-       { 0x31fa, 0x0000 },
-       { 0x31fb, 0xf000 },
-       { 0x31fc, 0x0000 },
-       { 0x31fd, 0xf000 },
-       { 0x31fe, 0x0000 },
-       { 0x31ff, 0xf000 },
-       { 0x024d, 0xff50 },
-       { 0x0252, 0xff50 },
-       { 0x0259, 0x0112 },
-       { 0x025e, 0x0112 },
-       { 0x101, 0x0304 },
        { 0x80, 0x0000 },
 };
 
index 172a768..21056b9 100644 (file)
@@ -57,6 +57,7 @@ MODULE_ALIAS("mmc:block");
 #define INAND_CMD38_ARG_SECERASE 0x80
 #define INAND_CMD38_ARG_SECTRIM1 0x81
 #define INAND_CMD38_ARG_SECTRIM2 0x88
+#define MMC_BLK_TIMEOUT_MS  (10 * 60 * 1000)        /* 10 minute timeout */
 
 static DEFINE_MUTEX(block_mutex);
 
@@ -126,6 +127,10 @@ enum mmc_blk_status {
 module_param(perdev_minors, int, 0444);
 MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device");
 
+static inline int mmc_blk_part_switch(struct mmc_card *card,
+                                     struct mmc_blk_data *md);
+static int get_card_status(struct mmc_card *card, u32 *status, int retries);
+
 static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
 {
        struct mmc_blk_data *md;
@@ -357,6 +362,38 @@ out:
        return ERR_PTR(err);
 }
 
+static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,
+                                      u32 retries_max)
+{
+       int err;
+       u32 retry_count = 0;
+
+       if (!status || !retries_max)
+               return -EINVAL;
+
+       do {
+               err = get_card_status(card, status, 5);
+               if (err)
+                       break;
+
+               if (!R1_STATUS(*status) &&
+                               (R1_CURRENT_STATE(*status) != R1_STATE_PRG))
+                       break; /* RPMB programming operation complete */
+
+               /*
+                * Rechedule to give the MMC device a chance to continue
+                * processing the previous command without being polled too
+                * frequently.
+                */
+               usleep_range(1000, 5000);
+       } while (++retry_count < retries_max);
+
+       if (retry_count == retries_max)
+               err = -EPERM;
+
+       return err;
+}
+
 static int mmc_blk_ioctl_cmd(struct block_device *bdev,
        struct mmc_ioc_cmd __user *ic_ptr)
 {
@@ -368,6 +405,8 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
        struct mmc_request mrq = {NULL};
        struct scatterlist sg;
        int err;
+       int is_rpmb = false;
+       u32 status = 0;
 
        /*
         * The caller must have CAP_SYS_RAWIO, and must be calling this on the
@@ -387,6 +426,9 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
                goto cmd_err;
        }
 
+       if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
+               is_rpmb = true;
+
        card = md->queue.card;
        if (IS_ERR(card)) {
                err = PTR_ERR(card);
@@ -437,12 +479,23 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
 
        mmc_claim_host(card->host);
 
+       err = mmc_blk_part_switch(card, md);
+       if (err)
+               goto cmd_rel_host;
+
        if (idata->ic.is_acmd) {
                err = mmc_app_cmd(card->host, card);
                if (err)
                        goto cmd_rel_host;
        }
 
+       if (is_rpmb) {
+               err = mmc_set_blockcount(card, data.blocks,
+                       idata->ic.write_flag & (1 << 31));
+               if (err)
+                       goto cmd_rel_host;
+       }
+
        mmc_wait_for_req(card->host, &mrq);
 
        if (cmd.error) {
@@ -478,6 +531,18 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
                }
        }
 
+       if (is_rpmb) {
+               /*
+                * Ensure RPMB command has completed by polling CMD13
+                * "Send Status".
+                */
+               err = ioctl_rpmb_card_status_poll(card, &status, 5);
+               if (err)
+                       dev_err(mmc_dev(card->host),
+                                       "%s: Card Status=0x%08X, error %d\n",
+                                       __func__, status, err);
+       }
+
 cmd_rel_host:
        mmc_release_host(card->host);
 
@@ -1034,6 +1099,9 @@ static int mmc_blk_err_check(struct mmc_card *card,
         */
        if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
                u32 status;
+               unsigned long timeout;
+
+               timeout = jiffies + msecs_to_jiffies(MMC_BLK_TIMEOUT_MS);
                do {
                        int err = get_card_status(card, &status, 5);
                        if (err) {
@@ -1041,6 +1109,17 @@ static int mmc_blk_err_check(struct mmc_card *card,
                                       req->rq_disk->disk_name, err);
                                return MMC_BLK_CMD_ERR;
                        }
+
+                       /* Timeout if the device never becomes ready for data
+                        * and never leaves the program state.
+                        */
+                       if (time_after(jiffies, timeout)) {
+                               pr_err("%s: Card stuck in programming state!"\
+                                       " %s %s\n", mmc_hostname(card->host),
+                                       req->rq_disk->disk_name, __func__);
+
+                               return MMC_BLK_CMD_ERR;
+                       }
                        /*
                         * Some cards mishandle the status bits,
                         * so make sure to check both the busy
@@ -1504,6 +1583,8 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
        md->disk->queue = md->queue.queue;
        md->disk->driverfs_dev = parent;
        set_disk_ro(md->disk, md->read_only || default_ro);
+       if (area_type & MMC_BLK_DATA_AREA_RPMB)
+               md->disk->flags |= GENHD_FL_NO_PART_SCAN;
 
        /*
         * As discussed on lkml, GENHD_FL_REMOVABLE should:
index e360a97..fadf52e 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 9b68933..420cb67 100644 (file)
@@ -225,8 +225,7 @@ static void mmc_release_card(struct device *dev)
 
        sdio_free_common_cis(card);
 
-       if (card->info)
-               kfree(card->info);
+       kfree(card->info);
 
        kfree(card);
 }
index 06c42cf..aaed768 100644 (file)
@@ -42,6 +42,9 @@
 #include "sd_ops.h"
 #include "sdio_ops.h"
 
+/* If the device is not responding */
+#define MMC_CORE_TIMEOUT_MS    (10 * 60 * 1000) /* 10 minute timeout */
+
 /*
  * Background operations can take a long time, depending on the housekeeping
  * operations the card has to perform.
@@ -1631,6 +1634,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
 {
        struct mmc_command cmd = {0};
        unsigned int qty = 0;
+       unsigned long timeout;
        int err;
 
        /*
@@ -1708,6 +1712,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
        if (mmc_host_is_spi(card->host))
                goto out;
 
+       timeout = jiffies + msecs_to_jiffies(MMC_CORE_TIMEOUT_MS);
        do {
                memset(&cmd, 0, sizeof(struct mmc_command));
                cmd.opcode = MMC_SEND_STATUS;
@@ -1721,8 +1726,19 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
                        err = -EIO;
                        goto out;
                }
+
+               /* Timeout if the device never becomes ready for data and
+                * never leaves the program state.
+                */
+               if (time_after(jiffies, timeout)) {
+                       pr_err("%s: Card stuck in programming state! %s\n",
+                               mmc_hostname(card->host), __func__);
+                       err =  -EIO;
+                       goto out;
+               }
+
        } while (!(cmd.resp[0] & R1_READY_FOR_DATA) ||
-                R1_CURRENT_STATE(cmd.resp[0]) == R1_STATE_PRG);
+                (R1_CURRENT_STATE(cmd.resp[0]) == R1_STATE_PRG));
 out:
        return err;
 }
@@ -1942,6 +1958,20 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen)
 }
 EXPORT_SYMBOL(mmc_set_blocklen);
 
+int mmc_set_blockcount(struct mmc_card *card, unsigned int blockcount,
+                       bool is_rel_write)
+{
+       struct mmc_command cmd = {0};
+
+       cmd.opcode = MMC_SET_BLOCK_COUNT;
+       cmd.arg = blockcount & 0x0000FFFF;
+       if (is_rel_write)
+               cmd.arg |= 1 << 31;
+       cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
+       return mmc_wait_for_cmd(card->host, &cmd, 5);
+}
+EXPORT_SYMBOL(mmc_set_blockcount);
+
 static void mmc_hw_reset_for_init(struct mmc_host *host)
 {
        if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
index d96c643..35c2f85 100644 (file)
@@ -144,6 +144,22 @@ static int mmc_ios_show(struct seq_file *s, void *data)
        }
        seq_printf(s, "timing spec:\t%u (%s)\n", ios->timing, str);
 
+       switch (ios->signal_voltage) {
+       case MMC_SIGNAL_VOLTAGE_330:
+               str = "3.30 V";
+               break;
+       case MMC_SIGNAL_VOLTAGE_180:
+               str = "1.80 V";
+               break;
+       case MMC_SIGNAL_VOLTAGE_120:
+               str = "1.20 V";
+               break;
+       default:
+               str = "invalid";
+               break;
+       }
+       seq_printf(s, "signal voltage:\t%u (%s)\n", ios->chip_select, str);
+
        return 0;
 }
 
index 7cc4638..e6e3911 100644 (file)
@@ -239,7 +239,7 @@ static void mmc_select_card_type(struct mmc_card *card)
 {
        struct mmc_host *host = card->host;
        u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
-       unsigned int caps = host->caps, caps2 = host->caps2;
+       u32 caps = host->caps, caps2 = host->caps2;
        unsigned int hs_max_dtr = 0;
 
        if (card_type & EXT_CSD_CARD_TYPE_26)
@@ -491,6 +491,17 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
 
                card->ext_csd.rel_param = ext_csd[EXT_CSD_WR_REL_PARAM];
                card->ext_csd.rst_n_function = ext_csd[EXT_CSD_RST_N_FUNCTION];
+
+               /*
+                * RPMB regions are defined in multiples of 128K.
+                */
+               card->ext_csd.raw_rpmb_size_mult = ext_csd[EXT_CSD_RPMB_MULT];
+               if (ext_csd[EXT_CSD_RPMB_MULT]) {
+                       mmc_part_add(card, ext_csd[EXT_CSD_RPMB_MULT] << 17,
+                               EXT_CSD_PART_CONFIG_ACC_RPMB,
+                               "rpmb", 0, false,
+                               MMC_BLK_DATA_AREA_RPMB);
+               }
        }
 
        card->ext_csd.raw_erased_mem_count = ext_csd[EXT_CSD_ERASED_MEM_CONT];
@@ -615,6 +626,8 @@ MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial);
 MMC_DEV_ATTR(enhanced_area_offset, "%llu\n",
                card->ext_csd.enhanced_area_offset);
 MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size);
+MMC_DEV_ATTR(raw_rpmb_size_mult, "%#x\n", card->ext_csd.raw_rpmb_size_mult);
+MMC_DEV_ATTR(rel_sectors, "%#x\n", card->ext_csd.rel_sectors);
 
 static struct attribute *mmc_std_attrs[] = {
        &dev_attr_cid.attr,
@@ -630,6 +643,8 @@ static struct attribute *mmc_std_attrs[] = {
        &dev_attr_serial.attr,
        &dev_attr_enhanced_area_offset.attr,
        &dev_attr_enhanced_area_size.attr,
+       &dev_attr_raw_rpmb_size_mult.attr,
+       &dev_attr_rel_sectors.attr,
        NULL,
 };
 
@@ -1051,6 +1066,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        if (mmc_card_highspeed(card) || mmc_card_hs200(card)) {
                if (max_dtr > card->ext_csd.hs_max_dtr)
                        max_dtr = card->ext_csd.hs_max_dtr;
+               if (mmc_card_highspeed(card) && (max_dtr > 52000000))
+                       max_dtr = 52000000;
        } else if (max_dtr > card->csd.max_dtr) {
                max_dtr = card->csd.max_dtr;
        }
index a0e1720..6d8f701 100644 (file)
@@ -21,6 +21,8 @@
 #include "core.h"
 #include "mmc_ops.h"
 
+#define MMC_OPS_TIMEOUT_MS     (10 * 60 * 1000) /* 10 minute timeout */
+
 static int _mmc_select_card(struct mmc_host *host, struct mmc_card *card)
 {
        int err;
@@ -409,6 +411,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 {
        int err;
        struct mmc_command cmd = {0};
+       unsigned long timeout;
        u32 status;
 
        BUG_ON(!card);
@@ -437,6 +440,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
                return 0;
 
        /* Must check status to be sure of no errors */
+       timeout = jiffies + msecs_to_jiffies(MMC_OPS_TIMEOUT_MS);
        do {
                err = mmc_send_status(card, &status);
                if (err)
@@ -445,6 +449,13 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
                        break;
                if (mmc_host_is_spi(card->host))
                        break;
+
+               /* Timeout if the device never leaves the program state. */
+               if (time_after(jiffies, timeout)) {
+                       pr_err("%s: Card stuck in programming state! %s\n",
+                               mmc_hostname(card->host), __func__);
+                       return -ETIMEDOUT;
+               }
        } while (R1_CURRENT_STATE(status) == R1_STATE_PRG);
 
        if (mmc_host_is_spi(card->host)) {
index 6bf6879..5e57048 100644 (file)
@@ -193,7 +193,21 @@ static int sdio_bus_remove(struct device *dev)
 }
 
 #ifdef CONFIG_PM
+
+#ifdef CONFIG_PM_SLEEP
+static int pm_no_operation(struct device *dev)
+{
+       /*
+        * Prevent the PM core from calling SDIO device drivers' suspend
+        * callback routines, which it is not supposed to do, by using this
+        * empty function as the bus type suspend callaback for SDIO.
+        */
+       return 0;
+}
+#endif
+
 static const struct dev_pm_ops sdio_bus_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(pm_no_operation, pm_no_operation)
        SET_RUNTIME_PM_OPS(
                pm_generic_runtime_suspend,
                pm_generic_runtime_resume,
@@ -258,8 +272,7 @@ static void sdio_release_func(struct device *dev)
 
        sdio_free_func_cis(func);
 
-       if (func->info)
-               kfree(func->info);
+       kfree(func->info);
 
        kfree(func);
 }
index 8f6f5ac..78cb4d5 100644 (file)
@@ -188,8 +188,7 @@ EXPORT_SYMBOL_GPL(sdio_set_block_size);
  */
 static inline unsigned int sdio_max_byte_size(struct sdio_func *func)
 {
-       unsigned mval = min(func->card->host->max_seg_size,
-                           func->card->host->max_blk_size);
+       unsigned mval = func->card->host->max_blk_size;
 
        if (mmc_blksz_for_byte_mode(func->card))
                mval = min(mval, func->cur_blksize);
@@ -311,11 +310,8 @@ static int sdio_io_rw_ext_helper(struct sdio_func *func, int write,
        /* Do the bulk of the transfer using block mode (if supported). */
        if (func->card->cccr.multi_block && (size > sdio_max_byte_size(func))) {
                /* Blocks per command is limited by host count, host transfer
-                * size (we only use a single sg entry) and the maximum for
-                * IO_RW_EXTENDED of 511 blocks. */
-               max_blocks = min(func->card->host->max_blk_count,
-                       func->card->host->max_seg_size / func->cur_blksize);
-               max_blocks = min(max_blocks, 511u);
+                * size and the maximum for IO_RW_EXTENDED of 511 blocks. */
+               max_blocks = min(func->card->host->max_blk_count, 511u);
 
                while (remainder >= func->cur_blksize) {
                        unsigned blocks;
index d29e206..62508b4 100644 (file)
@@ -124,7 +124,10 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
        struct mmc_request mrq = {NULL};
        struct mmc_command cmd = {0};
        struct mmc_data data = {0};
-       struct scatterlist sg;
+       struct scatterlist sg, *sg_ptr;
+       struct sg_table sgtable;
+       unsigned int nents, left_size, i;
+       unsigned int seg_size = card->host->max_seg_size;
 
        BUG_ON(!card);
        BUG_ON(fn > 7);
@@ -152,15 +155,36 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn,
        /* Code in host drivers/fwk assumes that "blocks" always is >=1 */
        data.blocks = blocks ? blocks : 1;
        data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
-       data.sg = &sg;
-       data.sg_len = 1;
 
-       sg_init_one(&sg, buf, data.blksz * data.blocks);
+       left_size = data.blksz * data.blocks;
+       nents = (left_size - 1) / seg_size + 1;
+       if (nents > 1) {
+               if (sg_alloc_table(&sgtable, nents, GFP_KERNEL))
+                       return -ENOMEM;
+
+               data.sg = sgtable.sgl;
+               data.sg_len = nents;
+
+               for_each_sg(data.sg, sg_ptr, data.sg_len, i) {
+                       sg_set_page(sg_ptr, virt_to_page(buf + (i * seg_size)),
+                                       min(seg_size, left_size),
+                                       offset_in_page(buf + (i * seg_size)));
+                       left_size = left_size - seg_size;
+               }
+       } else {
+               data.sg = &sg;
+               data.sg_len = 1;
+
+               sg_init_one(&sg, buf, left_size);
+       }
 
        mmc_set_data_timeout(&data, card);
 
        mmc_wait_for_req(card->host, &mrq);
 
+       if (nents > 1)
+               sg_free_table(&sgtable);
+
        if (cmd.error)
                return cmd.error;
        if (data.error)
index 08c6b3d..16a1c0b 100644 (file)
@@ -27,7 +27,13 @@ struct mmc_gpio {
 static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id)
 {
        /* Schedule a card detection after a debounce timeout */
-       mmc_detect_change(dev_id, msecs_to_jiffies(100));
+       struct mmc_host *host = dev_id;
+
+       if (host->ops->card_event)
+               host->ops->card_event(host);
+
+       mmc_detect_change(host, msecs_to_jiffies(200));
+
        return IRQ_HANDLED;
 }
 
index 9bf10e7..bebbe16 100644 (file)
@@ -81,6 +81,18 @@ config MMC_RICOH_MMC
 
          If unsure, say Y.
 
+config MMC_SDHCI_ACPI
+       tristate "SDHCI support for ACPI enumerated SDHCI controllers"
+       depends on MMC_SDHCI && ACPI
+       help
+         This selects support for ACPI enumerated SDHCI controllers,
+         identified by ACPI Compatibility ID PNP0D40 or specific
+         ACPI Hardware IDs.
+
+         If you have a controller with this interface, say Y or M here.
+
+         If unsure, say N.
+
 config MMC_SDHCI_PLTFM
        tristate "SDHCI platform and OF driver helper"
        depends on MMC_SDHCI
@@ -270,26 +282,8 @@ config MMC_AU1X
 
          If unsure, say N.
 
-choice
-       prompt "Atmel SD/MMC Driver"
-       depends on AVR32 || ARCH_AT91
-       default MMC_ATMELMCI if AVR32
-       help
-         Choose which driver to use for the Atmel MCI Silicon
-
-config MMC_AT91
-       tristate "AT91 SD/MMC Card Interface support (DEPRECATED)"
-       depends on ARCH_AT91
-       help
-         This selects the AT91 MCI controller. This driver will
-         be removed soon (for more information have a look to
-         Documentation/feature-removal-schedule.txt). Please use
-         MMC_ATMEL_MCI.
-
-         If unsure, say N.
-
 config MMC_ATMELMCI
-       tristate "Atmel Multimedia Card Interface support"
+       tristate "Atmel SD/MMC Driver (Multimedia Card Interface)"
        depends on AVR32 || ARCH_AT91
        help
          This selects the Atmel Multimedia Card Interface driver. If
@@ -298,8 +292,6 @@ config MMC_ATMELMCI
 
          If unsure, say N.
 
-endchoice
-
 config MMC_ATMELMCI_DMA
        bool "Atmel MCI DMA support"
        depends on MMC_ATMELMCI && (AVR32 || ARCH_AT91SAM9G45) && DMA_ENGINE
@@ -621,3 +613,14 @@ config MMC_USHC
 
          Note: These controllers only support SDIO cards and do not
          support MMC or SD memory cards.
+
+config MMC_WMT
+       tristate "Wondermedia SD/MMC Host Controller support"
+       depends on ARCH_VT8500
+       default y
+       help
+         This selects support for the SD/MMC Host Controller on
+         Wondermedia WM8505/WM8650 based SoCs.
+
+         To compile this driver as a module, choose M here: the
+         module will be called wmt-sdmmc.
index 17ad0a7..c5eddc1 100644 (file)
@@ -9,6 +9,7 @@ obj-$(CONFIG_MMC_MXS)           += mxs-mmc.o
 obj-$(CONFIG_MMC_SDHCI)                += sdhci.o
 obj-$(CONFIG_MMC_SDHCI_PCI)    += sdhci-pci.o
 obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI))       += sdhci-pci-data.o
+obj-$(CONFIG_MMC_SDHCI_ACPI)   += sdhci-acpi.o
 obj-$(CONFIG_MMC_SDHCI_PXAV3)  += sdhci-pxav3.o
 obj-$(CONFIG_MMC_SDHCI_PXAV2)  += sdhci-pxav2.o
 obj-$(CONFIG_MMC_SDHCI_S3C)    += sdhci-s3c.o
@@ -17,7 +18,6 @@ obj-$(CONFIG_MMC_WBSD)                += wbsd.o
 obj-$(CONFIG_MMC_AU1X)         += au1xmmc.o
 obj-$(CONFIG_MMC_OMAP)         += omap.o
 obj-$(CONFIG_MMC_OMAP_HS)      += omap_hsmmc.o
-obj-$(CONFIG_MMC_AT91)         += at91_mci.o
 obj-$(CONFIG_MMC_ATMELMCI)     += atmel-mci.o
 obj-$(CONFIG_MMC_TIFM_SD)      += tifm_sd.o
 obj-$(CONFIG_MMC_MSM)          += msm_sdcc.o
@@ -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_WMT)          += wmt-sdmmc.o
 
 obj-$(CONFIG_MMC_SDHCI_PLTFM)          += sdhci-pltfm.o
 obj-$(CONFIG_MMC_SDHCI_CNS3XXX)                += sdhci-cns3xxx.o
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
deleted file mode 100644 (file)
index 74bed0f..0000000
+++ /dev/null
@@ -1,1219 +0,0 @@
-/*
- *  linux/drivers/mmc/host/at91_mci.c - ATMEL AT91 MCI Driver
- *
- *  Copyright (C) 2005 Cougar Creek Computing Devices Ltd, All Rights Reserved
- *
- *  Copyright (C) 2006 Malcolm Noyes
- *
- * 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 AT91 MCI driver that has been tested with both MMC cards
-   and SD-cards.  Boards that support write protect are now supported.
-   The CCAT91SBC001 board does not support SD cards.
-
-   The three entry points are at91_mci_request, at91_mci_set_ios
-   and at91_mci_get_ro.
-
-   SET IOS
-     This configures the device to put it into the correct mode and clock speed
-     required.
-
-   MCI REQUEST
-     MCI request processes the commands sent in the mmc_request structure. This
-     can consist of a processing command and a stop command in the case of
-     multiple block transfers.
-
-     There are three main types of request, commands, reads and writes.
-
-     Commands are straight forward. The command is submitted to the controller and
-     the request function returns. When the controller generates an interrupt to indicate
-     the command is finished, the response to the command are read and the mmc_request_done
-     function called to end the request.
-
-     Reads and writes work in a similar manner to normal commands but involve the PDC (DMA)
-     controller to manage the transfers.
-
-     A read is done from the controller directly to the scatterlist passed in from the request.
-     Due to a bug in the AT91RM9200 controller, when a read is completed, all the words are byte
-     swapped in the scatterlist buffers.  AT91SAM926x are not affected by this bug.
-
-     The sequence of read interrupts is: ENDRX, RXBUFF, CMDRDY
-
-     A write is slightly different in that the bytes to write are read from the scatterlist
-     into a dma memory buffer (this is in case the source buffer should be read only). The
-     entire write buffer is then done from this single dma memory buffer.
-
-     The sequence of write interrupts is: ENDTX, TXBUFE, NOTBUSY, CMDRDY
-
-   GET RO
-     Gets the status of the write protect pin, if available.
-*/
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/dma-mapping.h>
-#include <linux/clk.h>
-#include <linux/atmel_pdc.h>
-#include <linux/gfp.h>
-#include <linux/highmem.h>
-
-#include <linux/mmc/host.h>
-#include <linux/mmc/sdio.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/gpio.h>
-
-#include <mach/board.h>
-#include <mach/cpu.h>
-
-#include "at91_mci.h"
-
-#define DRIVER_NAME "at91_mci"
-
-static inline int at91mci_is_mci1rev2xx(void)
-{
-       return (   cpu_is_at91sam9260()
-               || cpu_is_at91sam9263()
-               || cpu_is_at91sam9rl()
-               || cpu_is_at91sam9g10()
-               || cpu_is_at91sam9g20()
-               );
-}
-
-#define FL_SENT_COMMAND        (1 << 0)
-#define FL_SENT_STOP   (1 << 1)
-
-#define AT91_MCI_ERRORS        (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE       \
-               | AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE               \
-               | AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)
-
-#define at91_mci_read(host, reg)       __raw_readl((host)->baseaddr + (reg))
-#define at91_mci_write(host, reg, val) __raw_writel((val), (host)->baseaddr + (reg))
-
-#define MCI_BLKSIZE            512
-#define MCI_MAXBLKSIZE                 4095
-#define MCI_BLKATONCE          256
-#define MCI_BUFSIZE            (MCI_BLKSIZE * MCI_BLKATONCE)
-
-/*
- * Low level type for this driver
- */
-struct at91mci_host
-{
-       struct mmc_host *mmc;
-       struct mmc_command *cmd;
-       struct mmc_request *request;
-
-       void __iomem *baseaddr;
-       int irq;
-
-       struct at91_mmc_data *board;
-       int present;
-
-       struct clk *mci_clk;
-
-       /*
-        * Flag indicating when the command has been sent. This is used to
-        * work out whether or not to send the stop
-        */
-       unsigned int flags;
-       /* flag for current bus settings */
-       u32 bus_mode;
-
-       /* DMA buffer used for transmitting */
-       unsigned int* buffer;
-       dma_addr_t physical_address;
-       unsigned int total_length;
-
-       /* Latest in the scatterlist that has been enabled for transfer, but not freed */
-       int in_use_index;
-
-       /* Latest in the scatterlist that has been enabled for transfer */
-       int transfer_index;
-
-       /* Timer for timeouts */
-       struct timer_list timer;
-};
-
-/*
- * Reset the controller and restore most of the state
- */
-static void at91_reset_host(struct at91mci_host *host)
-{
-       unsigned long flags;
-       u32 mr;
-       u32 sdcr;
-       u32 dtor;
-       u32 imr;
-
-       local_irq_save(flags);
-       imr = at91_mci_read(host, AT91_MCI_IMR);
-
-       at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
-
-       /* save current state */
-       mr = at91_mci_read(host, AT91_MCI_MR) & 0x7fff;
-       sdcr = at91_mci_read(host, AT91_MCI_SDCR);
-       dtor = at91_mci_read(host, AT91_MCI_DTOR);
-
-       /* reset the controller */
-       at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
-
-       /* restore state */
-       at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
-       at91_mci_write(host, AT91_MCI_MR, mr);
-       at91_mci_write(host, AT91_MCI_SDCR, sdcr);
-       at91_mci_write(host, AT91_MCI_DTOR, dtor);
-       at91_mci_write(host, AT91_MCI_IER, imr);
-
-       /* make sure sdio interrupts will fire */
-       at91_mci_read(host, AT91_MCI_SR);
-
-       local_irq_restore(flags);
-}
-
-static void at91_timeout_timer(unsigned long data)
-{
-       struct at91mci_host *host;
-
-       host = (struct at91mci_host *)data;
-
-       if (host->request) {
-               dev_err(host->mmc->parent, "Timeout waiting end of packet\n");
-
-               if (host->cmd && host->cmd->data) {
-                       host->cmd->data->error = -ETIMEDOUT;
-               } else {
-                       if (host->cmd)
-                               host->cmd->error = -ETIMEDOUT;
-                       else
-                               host->request->cmd->error = -ETIMEDOUT;
-               }
-
-               at91_reset_host(host);
-               mmc_request_done(host->mmc, host->request);
-       }
-}
-
-/*
- * Copy from sg to a dma block - used for transfers
- */
-static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data *data)
-{
-       unsigned int len, i, size;
-       unsigned *dmabuf = host->buffer;
-
-       size = data->blksz * data->blocks;
-       len = data->sg_len;
-
-       /* MCI1 rev2xx Data Write Operation and number of bytes erratum */
-       if (at91mci_is_mci1rev2xx())
-               if (host->total_length == 12)
-                       memset(dmabuf, 0, 12);
-
-       /*
-        * Just loop through all entries. Size might not
-        * be the entire list though so make sure that
-        * we do not transfer too much.
-        */
-       for (i = 0; i < len; i++) {
-               struct scatterlist *sg;
-               int amount;
-               unsigned int *sgbuffer;
-
-               sg = &data->sg[i];
-
-               sgbuffer = kmap_atomic(sg_page(sg)) + sg->offset;
-               amount = min(size, sg->length);
-               size -= amount;
-
-               if (cpu_is_at91rm9200()) {      /* AT91RM9200 errata */
-                       int index;
-
-                       for (index = 0; index < (amount / 4); index++)
-                               *dmabuf++ = swab32(sgbuffer[index]);
-               } else {
-                       char *tmpv = (char *)dmabuf;
-                       memcpy(tmpv, sgbuffer, amount);
-                       tmpv += amount;
-                       dmabuf = (unsigned *)tmpv;
-               }
-
-               kunmap_atomic(sgbuffer);
-
-               if (size == 0)
-                       break;
-       }
-
-       /*
-        * Check that we didn't get a request to transfer
-        * more data than can fit into the SG list.
-        */
-       BUG_ON(size != 0);
-}
-
-/*
- * Handle after a dma read
- */
-static void at91_mci_post_dma_read(struct at91mci_host *host)
-{
-       struct mmc_command *cmd;
-       struct mmc_data *data;
-       unsigned int len, i, size;
-       unsigned *dmabuf = host->buffer;
-
-       pr_debug("post dma read\n");
-
-       cmd = host->cmd;
-       if (!cmd) {
-               pr_debug("no command\n");
-               return;
-       }
-
-       data = cmd->data;
-       if (!data) {
-               pr_debug("no data\n");
-               return;
-       }
-
-       size = data->blksz * data->blocks;
-       len = data->sg_len;
-
-       at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX);
-       at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
-
-       for (i = 0; i < len; i++) {
-               struct scatterlist *sg;
-               int amount;
-               unsigned int *sgbuffer;
-
-               sg = &data->sg[i];
-
-               sgbuffer = kmap_atomic(sg_page(sg)) + sg->offset;
-               amount = min(size, sg->length);
-               size -= amount;
-
-               if (cpu_is_at91rm9200()) {      /* AT91RM9200 errata */
-                       int index;
-                       for (index = 0; index < (amount / 4); index++)
-                               sgbuffer[index] = swab32(*dmabuf++);
-               } else {
-                       char *tmpv = (char *)dmabuf;
-                       memcpy(sgbuffer, tmpv, amount);
-                       tmpv += amount;
-                       dmabuf = (unsigned *)tmpv;
-               }
-
-               flush_kernel_dcache_page(sg_page(sg));
-               kunmap_atomic(sgbuffer);
-               data->bytes_xfered += amount;
-               if (size == 0)
-                       break;
-       }
-
-       pr_debug("post dma read done\n");
-}
-
-/*
- * Handle transmitted data
- */
-static void at91_mci_handle_transmitted(struct at91mci_host *host)
-{
-       struct mmc_command *cmd;
-       struct mmc_data *data;
-
-       pr_debug("Handling the transmit\n");
-
-       /* Disable the transfer */
-       at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
-
-       /* Now wait for cmd ready */
-       at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_TXBUFE);
-
-       cmd = host->cmd;
-       if (!cmd) return;
-
-       data = cmd->data;
-       if (!data) return;
-
-       if (cmd->data->blocks > 1) {
-               pr_debug("multiple write : wait for BLKE...\n");
-               at91_mci_write(host, AT91_MCI_IER, AT91_MCI_BLKE);
-       } else
-               at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
-}
-
-/*
- * Update bytes transfered count during a write operation
- */
-static void at91_mci_update_bytes_xfered(struct at91mci_host *host)
-{
-       struct mmc_data *data;
-
-       /* always deal with the effective request (and not the current cmd) */
-
-       if (host->request->cmd && host->request->cmd->error != 0)
-               return;
-
-       if (host->request->data) {
-               data = host->request->data;
-               if (data->flags & MMC_DATA_WRITE) {
-                       /* card is in IDLE mode now */
-                       pr_debug("-> bytes_xfered %d, total_length = %d\n",
-                               data->bytes_xfered, host->total_length);
-                       data->bytes_xfered = data->blksz * data->blocks;
-               }
-       }
-}
-
-
-/*Handle after command sent ready*/
-static int at91_mci_handle_cmdrdy(struct at91mci_host *host)
-{
-       if (!host->cmd)
-               return 1;
-       else if (!host->cmd->data) {
-               if (host->flags & FL_SENT_STOP) {
-                       /*After multi block write, we must wait for NOTBUSY*/
-                       at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
-               } else return 1;
-       } else if (host->cmd->data->flags & MMC_DATA_WRITE) {
-               /*After sendding multi-block-write command, start DMA transfer*/
-               at91_mci_write(host, AT91_MCI_IER, AT91_MCI_TXBUFE | AT91_MCI_BLKE);
-               at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
-       }
-
-       /* command not completed, have to wait */
-       return 0;
-}
-
-
-/*
- * Enable the controller
- */
-static void at91_mci_enable(struct at91mci_host *host)
-{
-       unsigned int mr;
-
-       at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
-       at91_mci_write(host, AT91_MCI_IDR, 0xffffffff);
-       at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
-       mr = AT91_MCI_PDCMODE | 0x34a;
-
-       if (at91mci_is_mci1rev2xx())
-               mr |= AT91_MCI_RDPROOF | AT91_MCI_WRPROOF;
-
-       at91_mci_write(host, AT91_MCI_MR, mr);
-
-       /* use Slot A or B (only one at same time) */
-       at91_mci_write(host, AT91_MCI_SDCR, host->board->slot_b);
-}
-
-/*
- * Disable the controller
- */
-static void at91_mci_disable(struct at91mci_host *host)
-{
-       at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS | AT91_MCI_SWRST);
-}
-
-/*
- * Send a command
- */
-static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command *cmd)
-{
-       unsigned int cmdr, mr;
-       unsigned int block_length;
-       struct mmc_data *data = cmd->data;
-
-       unsigned int blocks;
-       unsigned int ier = 0;
-
-       host->cmd = cmd;
-
-       /* Needed for leaving busy state before CMD1 */
-       if ((at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
-               pr_debug("Clearing timeout\n");
-               at91_mci_write(host, AT91_MCI_ARGR, 0);
-               at91_mci_write(host, AT91_MCI_CMDR, AT91_MCI_OPDCMD);
-               while (!(at91_mci_read(host, AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
-                       /* spin */
-                       pr_debug("Clearing: SR = %08X\n", at91_mci_read(host, AT91_MCI_SR));
-               }
-       }
-
-       cmdr = cmd->opcode;
-
-       if (mmc_resp_type(cmd) == MMC_RSP_NONE)
-               cmdr |= AT91_MCI_RSPTYP_NONE;
-       else {
-               /* if a response is expected then allow maximum response latancy */
-               cmdr |= AT91_MCI_MAXLAT;
-               /* set 136 bit response for R2, 48 bit response otherwise */
-               if (mmc_resp_type(cmd) == MMC_RSP_R2)
-                       cmdr |= AT91_MCI_RSPTYP_136;
-               else
-                       cmdr |= AT91_MCI_RSPTYP_48;
-       }
-
-       if (data) {
-
-               if (cpu_is_at91rm9200() || cpu_is_at91sam9261()) {
-                       if (data->blksz & 0x3) {
-                               pr_debug("Unsupported block size\n");
-                               cmd->error = -EINVAL;
-                               mmc_request_done(host->mmc, host->request);
-                               return;
-                       }
-                       if (data->flags & MMC_DATA_STREAM) {
-                               pr_debug("Stream commands not supported\n");
-                               cmd->error = -EINVAL;
-                               mmc_request_done(host->mmc, host->request);
-                               return;
-                       }
-               }
-
-               block_length = data->blksz;
-               blocks = data->blocks;
-
-               /* always set data start - also set direction flag for read */
-               if (data->flags & MMC_DATA_READ)
-                       cmdr |= (AT91_MCI_TRDIR | AT91_MCI_TRCMD_START);
-               else if (data->flags & MMC_DATA_WRITE)
-                       cmdr |= AT91_MCI_TRCMD_START;
-
-               if (cmd->opcode == SD_IO_RW_EXTENDED) {
-                       cmdr |= AT91_MCI_TRTYP_SDIO_BLOCK;
-               } else {
-                       if (data->flags & MMC_DATA_STREAM)
-                               cmdr |= AT91_MCI_TRTYP_STREAM;
-                       if (data->blocks > 1)
-                               cmdr |= AT91_MCI_TRTYP_MULTIPLE;
-               }
-       }
-       else {
-               block_length = 0;
-               blocks = 0;
-       }
-
-       if (host->flags & FL_SENT_STOP)
-               cmdr |= AT91_MCI_TRCMD_STOP;
-
-       if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
-               cmdr |= AT91_MCI_OPDCMD;
-
-       /*
-        * Set the arguments and send the command
-        */
-       pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08X)\n",
-               cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(host, AT91_MCI_MR));
-
-       if (!data) {
-               at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS | ATMEL_PDC_RXTDIS);
-               at91_mci_write(host, ATMEL_PDC_RPR, 0);
-               at91_mci_write(host, ATMEL_PDC_RCR, 0);
-               at91_mci_write(host, ATMEL_PDC_RNPR, 0);
-               at91_mci_write(host, ATMEL_PDC_RNCR, 0);
-               at91_mci_write(host, ATMEL_PDC_TPR, 0);
-               at91_mci_write(host, ATMEL_PDC_TCR, 0);
-               at91_mci_write(host, ATMEL_PDC_TNPR, 0);
-               at91_mci_write(host, ATMEL_PDC_TNCR, 0);
-               ier = AT91_MCI_CMDRDY;
-       } else {
-               /* zero block length and PDC mode */
-               mr = at91_mci_read(host, AT91_MCI_MR) & 0x5fff;
-               mr |= (data->blksz & 0x3) ? AT91_MCI_PDCFBYTE : 0;
-               mr |= (block_length << 16);
-               mr |= AT91_MCI_PDCMODE;
-               at91_mci_write(host, AT91_MCI_MR, mr);
-
-               if (!(cpu_is_at91rm9200() || cpu_is_at91sam9261()))
-                       at91_mci_write(host, AT91_MCI_BLKR,
-                               AT91_MCI_BLKR_BCNT(blocks) |
-                               AT91_MCI_BLKR_BLKLEN(block_length));
-
-               /*
-                * Disable the PDC controller
-                */
-               at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
-
-               if (cmdr & AT91_MCI_TRCMD_START) {
-                       data->bytes_xfered = 0;
-                       host->transfer_index = 0;
-                       host->in_use_index = 0;
-                       if (cmdr & AT91_MCI_TRDIR) {
-                               /*
-                                * Handle a read
-                                */
-                               host->total_length = 0;
-
-                               at91_mci_write(host, ATMEL_PDC_RPR, host->physical_address);
-                               at91_mci_write(host, ATMEL_PDC_RCR, (data->blksz & 0x3) ?
-                                       (blocks * block_length) : (blocks * block_length) / 4);
-                               at91_mci_write(host, ATMEL_PDC_RNPR, 0);
-                               at91_mci_write(host, ATMEL_PDC_RNCR, 0);
-
-                               ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
-                       }
-                       else {
-                               /*
-                                * Handle a write
-                                */
-                               host->total_length = block_length * blocks;
-                               /*
-                                * MCI1 rev2xx Data Write Operation and
-                                * number of bytes erratum
-                                */
-                               if (at91mci_is_mci1rev2xx())
-                                       if (host->total_length < 12)
-                                               host->total_length = 12;
-
-                               at91_mci_sg_to_dma(host, data);
-
-                               pr_debug("Transmitting %d bytes\n", host->total_length);
-
-                               at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
-                               at91_mci_write(host, ATMEL_PDC_TCR, (data->blksz & 0x3) ?
-                                               host->total_length : host->total_length / 4);
-
-                               ier = AT91_MCI_CMDRDY;
-                       }
-               }
-       }
-
-       /*
-        * Send the command and then enable the PDC - not the other way round as
-        * the data sheet says
-        */
-
-       at91_mci_write(host, AT91_MCI_ARGR, cmd->arg);
-       at91_mci_write(host, AT91_MCI_CMDR, cmdr);
-
-       if (cmdr & AT91_MCI_TRCMD_START) {
-               if (cmdr & AT91_MCI_TRDIR)
-                       at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
-       }
-
-       /* Enable selected interrupts */
-       at91_mci_write(host, AT91_MCI_IER, AT91_MCI_ERRORS | ier);
-}
-
-/*
- * Process the next step in the request
- */
-static void at91_mci_process_next(struct at91mci_host *host)
-{
-       if (!(host->flags & FL_SENT_COMMAND)) {
-               host->flags |= FL_SENT_COMMAND;
-               at91_mci_send_command(host, host->request->cmd);
-       }
-       else if ((!(host->flags & FL_SENT_STOP)) && host->request->stop) {
-               host->flags |= FL_SENT_STOP;
-               at91_mci_send_command(host, host->request->stop);
-       } else {
-               del_timer(&host->timer);
-               /* the at91rm9200 mci controller hangs after some transfers,
-                * and the workaround is to reset it after each transfer.
-                */
-               if (cpu_is_at91rm9200())
-                       at91_reset_host(host);
-               mmc_request_done(host->mmc, host->request);
-       }
-}
-
-/*
- * Handle a command that has been completed
- */
-static void at91_mci_completed_command(struct at91mci_host *host, unsigned int status)
-{
-       struct mmc_command *cmd = host->cmd;
-       struct mmc_data *data = cmd->data;
-
-       at91_mci_write(host, AT91_MCI_IDR, 0xffffffff & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
-
-       cmd->resp[0] = at91_mci_read(host, AT91_MCI_RSPR(0));
-       cmd->resp[1] = at91_mci_read(host, AT91_MCI_RSPR(1));
-       cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2));
-       cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3));
-
-       pr_debug("Status = %08X/%08x [%08X %08X %08X %08X]\n",
-                status, at91_mci_read(host, AT91_MCI_SR),
-                cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
-
-       if (status & AT91_MCI_ERRORS) {
-               if ((status & AT91_MCI_RCRCE) && !(mmc_resp_type(cmd) & MMC_RSP_CRC)) {
-                       cmd->error = 0;
-               }
-               else {
-                       if (status & (AT91_MCI_DTOE | AT91_MCI_DCRCE)) {
-                               if (data) {
-                                       if (status & AT91_MCI_DTOE)
-                                               data->error = -ETIMEDOUT;
-                                       else if (status & AT91_MCI_DCRCE)
-                                               data->error = -EILSEQ;
-                               }
-                       } else {
-                               if (status & AT91_MCI_RTOE)
-                                       cmd->error = -ETIMEDOUT;
-                               else if (status & AT91_MCI_RCRCE)
-                                       cmd->error = -EILSEQ;
-                               else
-                                       cmd->error = -EIO;
-                       }
-
-                       pr_debug("Error detected and set to %d/%d (cmd = %d, retries = %d)\n",
-                               cmd->error, data ? data->error : 0,
-                                cmd->opcode, cmd->retries);
-               }
-       }
-       else
-               cmd->error = 0;
-
-       at91_mci_process_next(host);
-}
-
-/*
- * Handle an MMC request
- */
-static void at91_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
-{
-       struct at91mci_host *host = mmc_priv(mmc);
-       host->request = mrq;
-       host->flags = 0;
-
-       /* more than 1s timeout needed with slow SD cards */
-       mod_timer(&host->timer, jiffies +  msecs_to_jiffies(2000));
-
-       at91_mci_process_next(host);
-}
-
-/*
- * Set the IOS
- */
-static void at91_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
-{
-       int clkdiv;
-       struct at91mci_host *host = mmc_priv(mmc);
-       unsigned long at91_master_clock = clk_get_rate(host->mci_clk);
-
-       host->bus_mode = ios->bus_mode;
-
-       if (ios->clock == 0) {
-               /* Disable the MCI controller */
-               at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIDIS);
-               clkdiv = 0;
-       }
-       else {
-               /* Enable the MCI controller */
-               at91_mci_write(host, AT91_MCI_CR, AT91_MCI_MCIEN);
-
-               if ((at91_master_clock % (ios->clock * 2)) == 0)
-                       clkdiv = ((at91_master_clock / ios->clock) / 2) - 1;
-               else
-                       clkdiv = (at91_master_clock / ios->clock) / 2;
-
-               pr_debug("clkdiv = %d. mcck = %ld\n", clkdiv,
-                       at91_master_clock / (2 * (clkdiv + 1)));
-       }
-       if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) {
-               pr_debug("MMC: Setting controller bus width to 4\n");
-               at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) | AT91_MCI_SDCBUS);
-       }
-       else {
-               pr_debug("MMC: Setting controller bus width to 1\n");
-               at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
-       }
-
-       /* Set the clock divider */
-       at91_mci_write(host, AT91_MCI_MR, (at91_mci_read(host, AT91_MCI_MR) & ~AT91_MCI_CLKDIV) | clkdiv);
-
-       /* maybe switch power to the card */
-       if (gpio_is_valid(host->board->vcc_pin)) {
-               switch (ios->power_mode) {
-                       case MMC_POWER_OFF:
-                               gpio_set_value(host->board->vcc_pin, 0);
-                               break;
-                       case MMC_POWER_UP:
-                               gpio_set_value(host->board->vcc_pin, 1);
-                               break;
-                       case MMC_POWER_ON:
-                               break;
-                       default:
-                               WARN_ON(1);
-               }
-       }
-}
-
-/*
- * Handle an interrupt
- */
-static irqreturn_t at91_mci_irq(int irq, void *devid)
-{
-       struct at91mci_host *host = devid;
-       int completed = 0;
-       unsigned int int_status, int_mask;
-
-       int_status = at91_mci_read(host, AT91_MCI_SR);
-       int_mask = at91_mci_read(host, AT91_MCI_IMR);
-
-       pr_debug("MCI irq: status = %08X, %08X, %08X\n", int_status, int_mask,
-               int_status & int_mask);
-
-       int_status = int_status & int_mask;
-
-       if (int_status & AT91_MCI_ERRORS) {
-               completed = 1;
-
-               if (int_status & AT91_MCI_UNRE)
-                       pr_debug("MMC: Underrun error\n");
-               if (int_status & AT91_MCI_OVRE)
-                       pr_debug("MMC: Overrun error\n");
-               if (int_status & AT91_MCI_DTOE)
-                       pr_debug("MMC: Data timeout\n");
-               if (int_status & AT91_MCI_DCRCE)
-                       pr_debug("MMC: CRC error in data\n");
-               if (int_status & AT91_MCI_RTOE)
-                       pr_debug("MMC: Response timeout\n");
-               if (int_status & AT91_MCI_RENDE)
-                       pr_debug("MMC: Response end bit error\n");
-               if (int_status & AT91_MCI_RCRCE)
-                       pr_debug("MMC: Response CRC error\n");
-               if (int_status & AT91_MCI_RDIRE)
-                       pr_debug("MMC: Response direction error\n");
-               if (int_status & AT91_MCI_RINDE)
-                       pr_debug("MMC: Response index error\n");
-       } else {
-               /* Only continue processing if no errors */
-
-               if (int_status & AT91_MCI_TXBUFE) {
-                       pr_debug("TX buffer empty\n");
-                       at91_mci_handle_transmitted(host);
-               }
-
-               if (int_status & AT91_MCI_ENDRX) {
-                       pr_debug("ENDRX\n");
-                       at91_mci_post_dma_read(host);
-               }
-
-               if (int_status & AT91_MCI_RXBUFF) {
-                       pr_debug("RX buffer full\n");
-                       at91_mci_write(host, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS | ATMEL_PDC_TXTDIS);
-                       at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_RXBUFF | AT91_MCI_ENDRX);
-                       completed = 1;
-               }
-
-               if (int_status & AT91_MCI_ENDTX)
-                       pr_debug("Transmit has ended\n");
-
-               if (int_status & AT91_MCI_NOTBUSY) {
-                       pr_debug("Card is ready\n");
-                       at91_mci_update_bytes_xfered(host);
-                       completed = 1;
-               }
-
-               if (int_status & AT91_MCI_DTIP)
-                       pr_debug("Data transfer in progress\n");
-
-               if (int_status & AT91_MCI_BLKE) {
-                       pr_debug("Block transfer has ended\n");
-                       if (host->request->data && host->request->data->blocks > 1) {
-                               /* multi block write : complete multi write
-                                * command and send stop */
-                               completed = 1;
-                       } else {
-                               at91_mci_write(host, AT91_MCI_IER, AT91_MCI_NOTBUSY);
-                       }
-               }
-
-               if (int_status & AT91_MCI_SDIOIRQA)
-                       mmc_signal_sdio_irq(host->mmc);
-
-               if (int_status & AT91_MCI_SDIOIRQB)
-                       mmc_signal_sdio_irq(host->mmc);
-
-               if (int_status & AT91_MCI_TXRDY)
-                       pr_debug("Ready to transmit\n");
-
-               if (int_status & AT91_MCI_RXRDY)
-                       pr_debug("Ready to receive\n");
-
-               if (int_status & AT91_MCI_CMDRDY) {
-                       pr_debug("Command ready\n");
-                       completed = at91_mci_handle_cmdrdy(host);
-               }
-       }
-
-       if (completed) {
-               pr_debug("Completed command\n");
-               at91_mci_write(host, AT91_MCI_IDR, 0xffffffff & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
-               at91_mci_completed_command(host, int_status);
-       } else
-               at91_mci_write(host, AT91_MCI_IDR, int_status & ~(AT91_MCI_SDIOIRQA | AT91_MCI_SDIOIRQB));
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
-{
-       struct at91mci_host *host = _host;
-       int present;
-
-       /* entering this ISR means that we have configured det_pin:
-        * we can use its value in board structure */
-       present = !gpio_get_value(host->board->det_pin);
-
-       /*
-        * we expect this irq on both insert and remove,
-        * and use a short delay to debounce.
-        */
-       if (present != host->present) {
-               host->present = present;
-               pr_debug("%s: card %s\n", mmc_hostname(host->mmc),
-                       present ? "insert" : "remove");
-               if (!present) {
-                       pr_debug("****** Resetting SD-card bus width ******\n");
-                       at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
-               }
-               /* 0.5s needed because of early card detect switch firing */
-               mmc_detect_change(host->mmc, msecs_to_jiffies(500));
-       }
-       return IRQ_HANDLED;
-}
-
-static int at91_mci_get_ro(struct mmc_host *mmc)
-{
-       struct at91mci_host *host = mmc_priv(mmc);
-
-       if (gpio_is_valid(host->board->wp_pin))
-               return !!gpio_get_value(host->board->wp_pin);
-       /*
-        * Board doesn't support read only detection; let the mmc core
-        * decide what to do.
-        */
-       return -ENOSYS;
-}
-
-static void at91_mci_enable_sdio_irq(struct mmc_host *mmc, int enable)
-{
-       struct at91mci_host *host = mmc_priv(mmc);
-
-       pr_debug("%s: sdio_irq %c : %s\n", mmc_hostname(host->mmc),
-               host->board->slot_b ? 'B':'A', enable ? "enable" : "disable");
-       at91_mci_write(host, enable ? AT91_MCI_IER : AT91_MCI_IDR,
-               host->board->slot_b ? AT91_MCI_SDIOIRQB : AT91_MCI_SDIOIRQA);
-
-}
-
-static const struct mmc_host_ops at91_mci_ops = {
-       .request        = at91_mci_request,
-       .set_ios        = at91_mci_set_ios,
-       .get_ro         = at91_mci_get_ro,
-       .enable_sdio_irq = at91_mci_enable_sdio_irq,
-};
-
-/*
- * Probe for the device
- */
-static int __init at91_mci_probe(struct platform_device *pdev)
-{
-       struct mmc_host *mmc;
-       struct at91mci_host *host;
-       struct resource *res;
-       int ret;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -ENXIO;
-
-       if (!request_mem_region(res->start, resource_size(res), DRIVER_NAME))
-               return -EBUSY;
-
-       mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
-       if (!mmc) {
-               ret = -ENOMEM;
-               dev_dbg(&pdev->dev, "couldn't allocate mmc host\n");
-               goto fail6;
-       }
-
-       mmc->ops = &at91_mci_ops;
-       mmc->f_min = 375000;
-       mmc->f_max = 25000000;
-       mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
-       mmc->caps = 0;
-
-       mmc->max_blk_size  = MCI_MAXBLKSIZE;
-       mmc->max_blk_count = MCI_BLKATONCE;
-       mmc->max_req_size  = MCI_BUFSIZE;
-       mmc->max_segs      = MCI_BLKATONCE;
-       mmc->max_seg_size  = MCI_BUFSIZE;
-
-       host = mmc_priv(mmc);
-       host->mmc = mmc;
-       host->bus_mode = 0;
-       host->board = pdev->dev.platform_data;
-       if (host->board->wire4) {
-               if (at91mci_is_mci1rev2xx())
-                       mmc->caps |= MMC_CAP_4_BIT_DATA;
-               else
-                       dev_warn(&pdev->dev, "4 wire bus mode not supported"
-                               " - using 1 wire\n");
-       }
-
-       host->buffer = dma_alloc_coherent(&pdev->dev, MCI_BUFSIZE,
-                                       &host->physical_address, GFP_KERNEL);
-       if (!host->buffer) {
-               ret = -ENOMEM;
-               dev_err(&pdev->dev, "Can't allocate transmit buffer\n");
-               goto fail5;
-       }
-
-       /* Add SDIO capability when available */
-       if (at91mci_is_mci1rev2xx()) {
-               /* at91mci MCI1 rev2xx sdio interrupt erratum */
-               if (host->board->wire4 || !host->board->slot_b)
-                       mmc->caps |= MMC_CAP_SDIO_IRQ;
-       }
-
-       /*
-        * Reserve GPIOs ... board init code makes sure these pins are set
-        * up as GPIOs with the right direction (input, except for vcc)
-        */
-       if (gpio_is_valid(host->board->det_pin)) {
-               ret = gpio_request(host->board->det_pin, "mmc_detect");
-               if (ret < 0) {
-                       dev_dbg(&pdev->dev, "couldn't claim card detect pin\n");
-                       goto fail4b;
-               }
-       }
-       if (gpio_is_valid(host->board->wp_pin)) {
-               ret = gpio_request(host->board->wp_pin, "mmc_wp");
-               if (ret < 0) {
-                       dev_dbg(&pdev->dev, "couldn't claim wp sense pin\n");
-                       goto fail4;
-               }
-       }
-       if (gpio_is_valid(host->board->vcc_pin)) {
-               ret = gpio_request(host->board->vcc_pin, "mmc_vcc");
-               if (ret < 0) {
-                       dev_dbg(&pdev->dev, "couldn't claim vcc switch pin\n");
-                       goto fail3;
-               }
-       }
-
-       /*
-        * Get Clock
-        */
-       host->mci_clk = clk_get(&pdev->dev, "mci_clk");
-       if (IS_ERR(host->mci_clk)) {
-               ret = -ENODEV;
-               dev_dbg(&pdev->dev, "no mci_clk?\n");
-               goto fail2;
-       }
-
-       /*
-        * Map I/O region
-        */
-       host->baseaddr = ioremap(res->start, resource_size(res));
-       if (!host->baseaddr) {
-               ret = -ENOMEM;
-               goto fail1;
-       }
-
-       /*
-        * Reset hardware
-        */
-       clk_enable(host->mci_clk);              /* Enable the peripheral clock */
-       at91_mci_disable(host);
-       at91_mci_enable(host);
-
-       /*
-        * Allocate the MCI interrupt
-        */
-       host->irq = platform_get_irq(pdev, 0);
-       ret = request_irq(host->irq, at91_mci_irq, IRQF_SHARED,
-                       mmc_hostname(mmc), host);
-       if (ret) {
-               dev_dbg(&pdev->dev, "request MCI interrupt failed\n");
-               goto fail0;
-       }
-
-       setup_timer(&host->timer, at91_timeout_timer, (unsigned long)host);
-
-       platform_set_drvdata(pdev, mmc);
-
-       /*
-        * Add host to MMC layer
-        */
-       if (gpio_is_valid(host->board->det_pin)) {
-               host->present = !gpio_get_value(host->board->det_pin);
-       }
-       else
-               host->present = -1;
-
-       mmc_add_host(mmc);
-
-       /*
-        * monitor card insertion/removal if we can
-        */
-       if (gpio_is_valid(host->board->det_pin)) {
-               ret = request_irq(gpio_to_irq(host->board->det_pin),
-                               at91_mmc_det_irq, 0, mmc_hostname(mmc), host);
-               if (ret)
-                       dev_warn(&pdev->dev, "request MMC detect irq failed\n");
-               else
-                       device_init_wakeup(&pdev->dev, 1);
-       }
-
-       pr_debug("Added MCI driver\n");
-
-       return 0;
-
-fail0:
-       clk_disable(host->mci_clk);
-       iounmap(host->baseaddr);
-fail1:
-       clk_put(host->mci_clk);
-fail2:
-       if (gpio_is_valid(host->board->vcc_pin))
-               gpio_free(host->board->vcc_pin);
-fail3:
-       if (gpio_is_valid(host->board->wp_pin))
-               gpio_free(host->board->wp_pin);
-fail4:
-       if (gpio_is_valid(host->board->det_pin))
-               gpio_free(host->board->det_pin);
-fail4b:
-       if (host->buffer)
-               dma_free_coherent(&pdev->dev, MCI_BUFSIZE,
-                               host->buffer, host->physical_address);
-fail5:
-       mmc_free_host(mmc);
-fail6:
-       release_mem_region(res->start, resource_size(res));
-       dev_err(&pdev->dev, "probe failed, err %d\n", ret);
-       return ret;
-}
-
-/*
- * Remove a device
- */
-static int __exit at91_mci_remove(struct platform_device *pdev)
-{
-       struct mmc_host *mmc = platform_get_drvdata(pdev);
-       struct at91mci_host *host;
-       struct resource *res;
-
-       if (!mmc)
-               return -1;
-
-       host = mmc_priv(mmc);
-
-       if (host->buffer)
-               dma_free_coherent(&pdev->dev, MCI_BUFSIZE,
-                               host->buffer, host->physical_address);
-
-       if (gpio_is_valid(host->board->det_pin)) {
-               if (device_can_wakeup(&pdev->dev))
-                       free_irq(gpio_to_irq(host->board->det_pin), host);
-               device_init_wakeup(&pdev->dev, 0);
-               gpio_free(host->board->det_pin);
-       }
-
-       at91_mci_disable(host);
-       del_timer_sync(&host->timer);
-       mmc_remove_host(mmc);
-       free_irq(host->irq, host);
-
-       clk_disable(host->mci_clk);                     /* Disable the peripheral clock */
-       clk_put(host->mci_clk);
-
-       if (gpio_is_valid(host->board->vcc_pin))
-               gpio_free(host->board->vcc_pin);
-       if (gpio_is_valid(host->board->wp_pin))
-               gpio_free(host->board->wp_pin);
-
-       iounmap(host->baseaddr);
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(res->start, resource_size(res));
-
-       mmc_free_host(mmc);
-       platform_set_drvdata(pdev, NULL);
-       pr_debug("MCI Removed\n");
-
-       return 0;
-}
-
-#ifdef CONFIG_PM
-static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state)
-{
-       struct mmc_host *mmc = platform_get_drvdata(pdev);
-       struct at91mci_host *host = mmc_priv(mmc);
-       int ret = 0;
-
-       if (gpio_is_valid(host->board->det_pin) && device_may_wakeup(&pdev->dev))
-               enable_irq_wake(host->board->det_pin);
-
-       if (mmc)
-               ret = mmc_suspend_host(mmc);
-
-       return ret;
-}
-
-static int at91_mci_resume(struct platform_device *pdev)
-{
-       struct mmc_host *mmc = platform_get_drvdata(pdev);
-       struct at91mci_host *host = mmc_priv(mmc);
-       int ret = 0;
-
-       if (gpio_is_valid(host->board->det_pin) && device_may_wakeup(&pdev->dev))
-               disable_irq_wake(host->board->det_pin);
-
-       if (mmc)
-               ret = mmc_resume_host(mmc);
-
-       return ret;
-}
-#else
-#define at91_mci_suspend       NULL
-#define at91_mci_resume                NULL
-#endif
-
-static struct platform_driver at91_mci_driver = {
-       .remove         = __exit_p(at91_mci_remove),
-       .suspend        = at91_mci_suspend,
-       .resume         = at91_mci_resume,
-       .driver         = {
-               .name   = DRIVER_NAME,
-               .owner  = THIS_MODULE,
-       },
-};
-
-static int __init at91_mci_init(void)
-{
-       return platform_driver_probe(&at91_mci_driver, at91_mci_probe);
-}
-
-static void __exit at91_mci_exit(void)
-{
-       platform_driver_unregister(&at91_mci_driver);
-}
-
-module_init(at91_mci_init);
-module_exit(at91_mci_exit);
-
-MODULE_DESCRIPTION("AT91 Multimedia Card Interface driver");
-MODULE_AUTHOR("Nick Randell");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:at91_mci");
diff --git a/drivers/mmc/host/at91_mci.h b/drivers/mmc/host/at91_mci.h
deleted file mode 100644 (file)
index eec3a6b..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * drivers/mmc/host/at91_mci.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * MultiMedia Card Interface (MCI) registers.
- * Based on AT91RM9200 datasheet revision F.
- *
- * 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_MCI_H
-#define AT91_MCI_H
-
-#define AT91_MCI_CR            0x00            /* Control Register */
-#define                AT91_MCI_MCIEN          (1 <<  0)       /* Multi-Media Interface Enable */
-#define                AT91_MCI_MCIDIS         (1 <<  1)       /* Multi-Media Interface Disable */
-#define                AT91_MCI_PWSEN          (1 <<  2)       /* Power Save Mode Enable */
-#define                AT91_MCI_PWSDIS         (1 <<  3)       /* Power Save Mode Disable */
-#define                AT91_MCI_SWRST          (1 <<  7)       /* Software Reset */
-
-#define AT91_MCI_MR            0x04            /* Mode Register */
-#define                AT91_MCI_CLKDIV         (0xff  <<  0)   /* Clock Divider */
-#define                AT91_MCI_PWSDIV         (7     <<  8)   /* Power Saving Divider */
-#define                AT91_MCI_RDPROOF        (1     << 11)   /* Read Proof Enable [SAM926[03] only] */
-#define                AT91_MCI_WRPROOF        (1     << 12)   /* Write Proof Enable [SAM926[03] only] */
-#define                AT91_MCI_PDCFBYTE       (1     << 13)   /* PDC Force Byte Transfer [SAM926[03] only] */
-#define                AT91_MCI_PDCPADV        (1     << 14)   /* PDC Padding Value */
-#define                AT91_MCI_PDCMODE        (1     << 15)   /* PDC-orientated Mode */
-#define                AT91_MCI_BLKLEN         (0xfff << 18)   /* Data Block Length */
-
-#define AT91_MCI_DTOR          0x08            /* Data Timeout Register */
-#define                AT91_MCI_DTOCYC         (0xf << 0)      /* Data Timeout Cycle Number */
-#define                AT91_MCI_DTOMUL         (7   << 4)      /* Data Timeout Multiplier */
-#define                AT91_MCI_DTOMUL_1               (0 <<  4)
-#define                AT91_MCI_DTOMUL_16              (1 <<  4)
-#define                AT91_MCI_DTOMUL_128             (2 <<  4)
-#define                AT91_MCI_DTOMUL_256             (3 <<  4)
-#define                AT91_MCI_DTOMUL_1K              (4 <<  4)
-#define                AT91_MCI_DTOMUL_4K              (5 <<  4)
-#define                AT91_MCI_DTOMUL_64K             (6 <<  4)
-#define                AT91_MCI_DTOMUL_1M              (7 <<  4)
-
-#define AT91_MCI_SDCR          0x0c            /* SD Card Register */
-#define                AT91_MCI_SDCSEL         (3 << 0)        /* SD Card Selector */
-#define                AT91_MCI_SDCBUS         (1 << 7)        /* 1-bit or 4-bit bus */
-
-#define AT91_MCI_ARGR          0x10            /* Argument Register */
-
-#define AT91_MCI_CMDR          0x14            /* Command Register */
-#define                AT91_MCI_CMDNB          (0x3f << 0)     /* Command Number */
-#define                AT91_MCI_RSPTYP         (3    << 6)     /* Response Type */
-#define                        AT91_MCI_RSPTYP_NONE    (0 <<  6)
-#define                        AT91_MCI_RSPTYP_48      (1 <<  6)
-#define                        AT91_MCI_RSPTYP_136     (2 <<  6)
-#define                AT91_MCI_SPCMD          (7    << 8)     /* Special Command */
-#define                        AT91_MCI_SPCMD_NONE     (0 <<  8)
-#define                        AT91_MCI_SPCMD_INIT     (1 <<  8)
-#define                        AT91_MCI_SPCMD_SYNC     (2 <<  8)
-#define                        AT91_MCI_SPCMD_ICMD     (4 <<  8)
-#define                        AT91_MCI_SPCMD_IRESP    (5 <<  8)
-#define                AT91_MCI_OPDCMD         (1 << 11)       /* Open Drain Command */
-#define                AT91_MCI_MAXLAT         (1 << 12)       /* Max Latency for Command to Response */
-#define                AT91_MCI_TRCMD          (3 << 16)       /* Transfer Command */
-#define                        AT91_MCI_TRCMD_NONE     (0 << 16)
-#define                        AT91_MCI_TRCMD_START    (1 << 16)
-#define                        AT91_MCI_TRCMD_STOP     (2 << 16)
-#define                AT91_MCI_TRDIR          (1 << 18)       /* Transfer Direction */
-#define                AT91_MCI_TRTYP          (3 << 19)       /* Transfer Type */
-#define                        AT91_MCI_TRTYP_BLOCK    (0 << 19)
-#define                        AT91_MCI_TRTYP_MULTIPLE (1 << 19)
-#define                        AT91_MCI_TRTYP_STREAM   (2 << 19)
-#define                        AT91_MCI_TRTYP_SDIO_BYTE        (4 << 19)
-#define                        AT91_MCI_TRTYP_SDIO_BLOCK       (5 << 19)
-
-#define AT91_MCI_BLKR          0x18            /* Block Register */
-#define                AT91_MCI_BLKR_BCNT(n)   ((0xffff & (n)) << 0)   /* Block count */
-#define                AT91_MCI_BLKR_BLKLEN(n) ((0xffff & (n)) << 16)  /* Block length */
-
-#define AT91_MCI_RSPR(n)       (0x20 + ((n) * 4))      /* Response Registers 0-3 */
-#define AT91_MCR_RDR           0x30            /* Receive Data Register */
-#define AT91_MCR_TDR           0x34            /* Transmit Data Register */
-
-#define AT91_MCI_SR            0x40            /* Status Register */
-#define                AT91_MCI_CMDRDY         (1 <<  0)       /* Command Ready */
-#define                AT91_MCI_RXRDY          (1 <<  1)       /* Receiver Ready */
-#define                AT91_MCI_TXRDY          (1 <<  2)       /* Transmit Ready */
-#define                AT91_MCI_BLKE           (1 <<  3)       /* Data Block Ended */
-#define                AT91_MCI_DTIP           (1 <<  4)       /* Data Transfer in Progress */
-#define                AT91_MCI_NOTBUSY        (1 <<  5)       /* Data Not Busy */
-#define                AT91_MCI_ENDRX          (1 <<  6)       /* End of RX Buffer */
-#define                AT91_MCI_ENDTX          (1 <<  7)       /* End fo TX Buffer */
-#define                AT91_MCI_SDIOIRQA       (1 <<  8)       /* SDIO Interrupt for Slot A */
-#define                AT91_MCI_SDIOIRQB       (1 <<  9)       /* SDIO Interrupt for Slot B */
-#define                AT91_MCI_RXBUFF         (1 << 14)       /* RX Buffer Full */
-#define                AT91_MCI_TXBUFE         (1 << 15)       /* TX Buffer Empty */
-#define                AT91_MCI_RINDE          (1 << 16)       /* Response Index Error */
-#define                AT91_MCI_RDIRE          (1 << 17)       /* Response Direction Error */
-#define                AT91_MCI_RCRCE          (1 << 18)       /* Response CRC Error */
-#define                AT91_MCI_RENDE          (1 << 19)       /* Response End Bit Error */
-#define                AT91_MCI_RTOE           (1 << 20)       /* Response Time-out Error */
-#define                AT91_MCI_DCRCE          (1 << 21)       /* Data CRC Error */
-#define                AT91_MCI_DTOE           (1 << 22)       /* Data Time-out Error */
-#define                AT91_MCI_OVRE           (1 << 30)       /* Overrun */
-#define                AT91_MCI_UNRE           (1 << 31)       /* Underrun */
-
-#define AT91_MCI_IER           0x44            /* Interrupt Enable Register */
-#define AT91_MCI_IDR           0x48            /* Interrupt Disable Register */
-#define AT91_MCI_IMR           0x4c            /* Interrupt Mask Register */
-
-#endif
index 660bbc5..4d50da6 100644 (file)
@@ -208,7 +208,7 @@ static unsigned long exynos5250_dwmmc_caps[4] = {
        MMC_CAP_CMD23,
 };
 
-static struct dw_mci_drv_data exynos5250_drv_data = {
+static const struct dw_mci_drv_data exynos5250_drv_data = {
        .caps                   = exynos5250_dwmmc_caps,
        .init                   = dw_mci_exynos_priv_init,
        .setup_clock            = dw_mci_exynos_setup_clock,
@@ -220,14 +220,14 @@ static struct dw_mci_drv_data exynos5250_drv_data = {
 
 static const struct of_device_id dw_mci_exynos_match[] = {
        { .compatible = "samsung,exynos5250-dw-mshc",
-                       .data = (void *)&exynos5250_drv_data, },
+                       .data = &exynos5250_drv_data, },
        {},
 };
-MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match);
+MODULE_DEVICE_TABLE(of, dw_mci_exynos_match);
 
 int dw_mci_exynos_probe(struct platform_device *pdev)
 {
-       struct dw_mci_drv_data *drv_data;
+       const struct dw_mci_drv_data *drv_data;
        const struct of_device_id *match;
 
        match = of_match_node(dw_mci_exynos_match, pdev->dev.of_node);
index edb37e9..53a09cb 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 c960ca7..4e13370 100644 (file)
@@ -24,7 +24,7 @@
 #include "dw_mmc.h"
 
 int dw_mci_pltfm_register(struct platform_device *pdev,
-                               struct dw_mci_drv_data *drv_data)
+                               const struct dw_mci_drv_data *drv_data)
 {
        struct dw_mci *host;
        struct resource *regs;
@@ -50,8 +50,8 @@ int dw_mci_pltfm_register(struct platform_device *pdev,
        if (!host->regs)
                return -ENOMEM;
 
-       if (host->drv_data->init) {
-               ret = host->drv_data->init(host);
+       if (drv_data && drv_data->init) {
+               ret = drv_data->init(host);
                if (ret)
                        return ret;
        }
@@ -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 301f245..2ac37b8 100644 (file)
@@ -13,7 +13,7 @@
 #define _DW_MMC_PLTFM_H_
 
 extern int dw_mci_pltfm_register(struct platform_device *pdev,
-                               struct dw_mci_drv_data *drv_data);
+                               const struct dw_mci_drv_data *drv_data);
 extern int __devexit dw_mci_pltfm_remove(struct platform_device *pdev);
 extern const struct dev_pm_ops dw_mci_pltfm_pmops;
 
index c2828f3..323c502 100644 (file)
@@ -232,6 +232,7 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
 {
        struct mmc_data *data;
        struct dw_mci_slot *slot = mmc_priv(mmc);
+       const struct dw_mci_drv_data *drv_data = slot->host->drv_data;
        u32 cmdr;
        cmd->error = -EINPROGRESS;
 
@@ -261,8 +262,8 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
                        cmdr |= SDMMC_CMD_DAT_WR;
        }
 
-       if (slot->host->drv_data->prepare_command)
-               slot->host->drv_data->prepare_command(slot->host, &cmdr);
+       if (drv_data && drv_data->prepare_command)
+               drv_data->prepare_command(slot->host, &cmdr);
 
        return cmdr;
 }
@@ -434,7 +435,7 @@ static int dw_mci_idmac_init(struct dw_mci *host)
        return 0;
 }
 
-static struct dw_mci_dma_ops dw_mci_idmac_ops = {
+static const struct dw_mci_dma_ops dw_mci_idmac_ops = {
        .init = dw_mci_idmac_init,
        .start = dw_mci_idmac_start_dma,
        .stop = dw_mci_idmac_stop_dma,
@@ -616,13 +617,13 @@ static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg)
                cmd, arg, cmd_status);
 }
 
-static void dw_mci_setup_bus(struct dw_mci_slot *slot)
+static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)
 {
        struct dw_mci *host = slot->host;
        u32 div;
        u32 clk_en_a;
 
-       if (slot->clock != host->current_speed) {
+       if (slot->clock != host->current_speed || force_clkinit) {
                div = host->bus_hz / slot->clock;
                if (host->bus_hz % slot->clock && host->bus_hz > slot->clock)
                        /*
@@ -682,9 +683,6 @@ static void __dw_mci_start_request(struct dw_mci *host,
        if (host->pdata->select_slot)
                host->pdata->select_slot(slot->id);
 
-       /* Slot specific timing and width adjustment */
-       dw_mci_setup_bus(slot);
-
        host->cur_slot = slot;
        host->mrq = mrq;
 
@@ -772,21 +770,19 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
        struct dw_mci_slot *slot = mmc_priv(mmc);
+       const struct dw_mci_drv_data *drv_data = slot->host->drv_data;
        u32 regs;
 
-       /* set default 1 bit mode */
-       slot->ctype = SDMMC_CTYPE_1BIT;
-
        switch (ios->bus_width) {
-       case MMC_BUS_WIDTH_1:
-               slot->ctype = SDMMC_CTYPE_1BIT;
-               break;
        case MMC_BUS_WIDTH_4:
                slot->ctype = SDMMC_CTYPE_4BIT;
                break;
        case MMC_BUS_WIDTH_8:
                slot->ctype = SDMMC_CTYPE_8BIT;
                break;
+       default:
+               /* set default 1 bit mode */
+               slot->ctype = SDMMC_CTYPE_1BIT;
        }
 
        regs = mci_readl(slot->host, UHS_REG);
@@ -807,8 +803,11 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                slot->clock = ios->clock;
        }
 
-       if (slot->host->drv_data->set_ios)
-               slot->host->drv_data->set_ios(slot->host, ios);
+       if (drv_data && drv_data->set_ios)
+               drv_data->set_ios(slot->host, ios);
+
+       /* Slot specific timing and width adjustment */
+       dw_mci_setup_bus(slot, false);
 
        switch (ios->power_mode) {
        case MMC_POWER_UP:
@@ -1815,6 +1814,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
 {
        struct mmc_host *mmc;
        struct dw_mci_slot *slot;
+       const struct dw_mci_drv_data *drv_data = host->drv_data;
        int ctrl_id, ret;
        u8 bus_width;
 
@@ -1847,6 +1847,9 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
        if (host->pdata->caps)
                mmc->caps = host->pdata->caps;
 
+       if (host->pdata->pm_caps)
+               mmc->pm_caps = host->pdata->pm_caps;
+
        if (host->dev->of_node) {
                ctrl_id = of_alias_get_id(host->dev->of_node, "mshc");
                if (ctrl_id < 0)
@@ -1854,8 +1857,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
        } else {
                ctrl_id = to_platform_device(host->dev)->id;
        }
-       if (host->drv_data && host->drv_data->caps)
-               mmc->caps |= host->drv_data->caps[ctrl_id];
+       if (drv_data && drv_data->caps)
+               mmc->caps |= drv_data->caps[ctrl_id];
 
        if (host->pdata->caps2)
                mmc->caps2 = host->pdata->caps2;
@@ -1867,10 +1870,10 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
        else
                bus_width = 1;
 
-       if (host->drv_data->setup_bus) {
+       if (drv_data && drv_data->setup_bus) {
                struct device_node *slot_np;
                slot_np = dw_mci_of_find_slot_node(host->dev, slot->id);
-               ret = host->drv_data->setup_bus(host, slot_np, bus_width);
+               ret = drv_data->setup_bus(host, slot_np, bus_width);
                if (ret)
                        goto err_setup_bus;
        }
@@ -1908,7 +1911,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
 #endif /* CONFIG_MMC_DW_IDMAC */
        }
 
-       host->vmmc = regulator_get(mmc_dev(mmc), "vmmc");
+       host->vmmc = devm_regulator_get(mmc_dev(mmc), "vmmc");
        if (IS_ERR(host->vmmc)) {
                pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc));
                host->vmmc = NULL;
@@ -1957,7 +1960,7 @@ static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id)
 static void dw_mci_init_dma(struct dw_mci *host)
 {
        /* Alloc memory for sg translation */
-       host->sg_cpu = dma_alloc_coherent(host->dev, PAGE_SIZE,
+       host->sg_cpu = dmam_alloc_coherent(host->dev, PAGE_SIZE,
                                          &host->sg_dma, GFP_KERNEL);
        if (!host->sg_cpu) {
                dev_err(host->dev, "%s: could not alloc DMA memory\n",
@@ -1968,7 +1971,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)
@@ -2035,6 +2038,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
        struct dw_mci_board *pdata;
        struct device *dev = host->dev;
        struct device_node *np = dev->of_node;
+       const struct dw_mci_drv_data *drv_data = host->drv_data;
        int idx, ret;
 
        pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
@@ -2062,12 +2066,18 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
 
        of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms);
 
-       if (host->drv_data->parse_dt) {
-               ret = host->drv_data->parse_dt(host);
+       if (drv_data && drv_data->parse_dt) {
+               ret = drv_data->parse_dt(host);
                if (ret)
                        return ERR_PTR(ret);
        }
 
+       if (of_find_property(np, "keep-power-in-suspend", NULL))
+               pdata->pm_caps |= MMC_PM_KEEP_POWER;
+
+       if (of_find_property(np, "enable-sdio-wakeup", NULL))
+               pdata->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
+
        return pdata;
 }
 
@@ -2080,6 +2090,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
 
 int dw_mci_probe(struct dw_mci *host)
 {
+       const struct dw_mci_drv_data *drv_data = host->drv_data;
        int width, i, ret = 0;
        u32 fifo_size;
        int init_slots = 0;
@@ -2098,26 +2109,24 @@ int dw_mci_probe(struct dw_mci *host)
                return -ENODEV;
        }
 
-       host->biu_clk = clk_get(host->dev, "biu");
+       host->biu_clk = devm_clk_get(host->dev, "biu");
        if (IS_ERR(host->biu_clk)) {
                dev_dbg(host->dev, "biu clock not available\n");
        } else {
                ret = clk_prepare_enable(host->biu_clk);
                if (ret) {
                        dev_err(host->dev, "failed to enable biu clock\n");
-                       clk_put(host->biu_clk);
                        return ret;
                }
        }
 
-       host->ciu_clk = clk_get(host->dev, "ciu");
+       host->ciu_clk = devm_clk_get(host->dev, "ciu");
        if (IS_ERR(host->ciu_clk)) {
                dev_dbg(host->dev, "ciu clock not available\n");
        } else {
                ret = clk_prepare_enable(host->ciu_clk);
                if (ret) {
                        dev_err(host->dev, "failed to enable ciu clock\n");
-                       clk_put(host->ciu_clk);
                        goto err_clk_biu;
                }
        }
@@ -2127,8 +2136,8 @@ int dw_mci_probe(struct dw_mci *host)
        else
                host->bus_hz = clk_get_rate(host->ciu_clk);
 
-       if (host->drv_data->setup_clock) {
-               ret = host->drv_data->setup_clock(host);
+       if (drv_data && drv_data->setup_clock) {
+               ret = drv_data->setup_clock(host);
                if (ret) {
                        dev_err(host->dev,
                                "implementation specific clock setup failed\n");
@@ -2219,7 +2228,8 @@ int dw_mci_probe(struct dw_mci *host)
        if (!host->card_workqueue)
                goto err_dmaunmap;
        INIT_WORK(&host->card_work, dw_mci_work_routine_card);
-       ret = request_irq(host->irq, dw_mci_interrupt, host->irq_flags, "dw-mci", host);
+       ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt,
+                              host->irq_flags, "dw-mci", host);
        if (ret)
                goto err_workqueue;
 
@@ -2228,6 +2238,21 @@ int dw_mci_probe(struct dw_mci *host)
        else
                host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1;
 
+       /*
+        * Enable interrupts for command done, data over, data empty, card det,
+        * receive ready and error such as transmit, receive timeout, crc error
+        */
+       mci_writel(host, RINTSTS, 0xFFFFFFFF);
+       mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
+                  SDMMC_INT_TXDR | SDMMC_INT_RXDR |
+                  DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
+       mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
+
+       dev_info(host->dev, "DW MMC controller at irq %d, "
+                "%d bit host data width, "
+                "%u deep fifo\n",
+                host->irq, width, fifo_size);
+
        /* We need at least one slot to succeed */
        for (i = 0; i < host->num_slots; i++) {
                ret = dw_mci_init_slot(host, i);
@@ -2242,7 +2267,7 @@ int dw_mci_probe(struct dw_mci *host)
        } else {
                dev_dbg(host->dev, "attempted to initialize %d slots, "
                                        "but failed on all\n", host->num_slots);
-               goto err_init_slot;
+               goto err_workqueue;
        }
 
        /*
@@ -2257,52 +2282,29 @@ int dw_mci_probe(struct dw_mci *host)
        else
                host->data_offset = DATA_240A_OFFSET;
 
-       /*
-        * Enable interrupts for command done, data over, data empty, card det,
-        * receive ready and error such as transmit, receive timeout, crc error
-        */
-       mci_writel(host, RINTSTS, 0xFFFFFFFF);
-       mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
-                  SDMMC_INT_TXDR | SDMMC_INT_RXDR |
-                  DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
-       mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
-
-       dev_info(host->dev, "DW MMC controller at irq %d, "
-                "%d bit host data width, "
-                "%u deep fifo\n",
-                host->irq, width, fifo_size);
        if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)
                dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n");
 
        return 0;
 
-err_init_slot:
-       free_irq(host->irq, host);
-
 err_workqueue:
        destroy_workqueue(host->card_workqueue);
 
 err_dmaunmap:
        if (host->use_dma && host->dma_ops->exit)
                host->dma_ops->exit(host);
-       dma_free_coherent(host->dev, PAGE_SIZE,
-                         host->sg_cpu, host->sg_dma);
 
-       if (host->vmmc) {
+       if (host->vmmc)
                regulator_disable(host->vmmc);
-               regulator_put(host->vmmc);
-       }
 
 err_clk_ciu:
-       if (!IS_ERR(host->ciu_clk)) {
+       if (!IS_ERR(host->ciu_clk))
                clk_disable_unprepare(host->ciu_clk);
-               clk_put(host->ciu_clk);
-       }
+
 err_clk_biu:
-       if (!IS_ERR(host->biu_clk)) {
+       if (!IS_ERR(host->biu_clk))
                clk_disable_unprepare(host->biu_clk);
-               clk_put(host->biu_clk);
-       }
+
        return ret;
 }
 EXPORT_SYMBOL(dw_mci_probe);
@@ -2324,24 +2326,19 @@ void dw_mci_remove(struct dw_mci *host)
        mci_writel(host, CLKENA, 0);
        mci_writel(host, CLKSRC, 0);
 
-       free_irq(host->irq, host);
        destroy_workqueue(host->card_workqueue);
-       dma_free_coherent(host->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
 
        if (host->use_dma && host->dma_ops->exit)
                host->dma_ops->exit(host);
 
-       if (host->vmmc) {
+       if (host->vmmc)
                regulator_disable(host->vmmc);
-               regulator_put(host->vmmc);
-       }
 
        if (!IS_ERR(host->ciu_clk))
                clk_disable_unprepare(host->ciu_clk);
+
        if (!IS_ERR(host->biu_clk))
                clk_disable_unprepare(host->biu_clk);
-       clk_put(host->ciu_clk);
-       clk_put(host->biu_clk);
 }
 EXPORT_SYMBOL(dw_mci_remove);
 
@@ -2405,6 +2402,11 @@ int dw_mci_resume(struct dw_mci *host)
                struct dw_mci_slot *slot = host->slot[i];
                if (!slot)
                        continue;
+               if (slot->mmc->pm_flags & MMC_PM_KEEP_POWER) {
+                       dw_mci_set_ios(slot->mmc, &slot->mmc->ios);
+                       dw_mci_setup_bus(slot, true);
+               }
+
                ret = mmc_resume_host(host->slot[i]->mmc);
                if (ret < 0)
                        return ret;
index 565c2e4..29e680f 100644 (file)
@@ -240,7 +240,7 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
                return 0;
 
        for_each_sg(data->sg, sg, data->sg_len, i) {
-               if (sg->offset & 3 || sg->length & 3) {
+               if (sg->offset & 3 || sg->length & 3 || sg->length < 512) {
                        host->do_dma = 0;
                        return 0;
                }
@@ -1134,4 +1134,4 @@ module_platform_driver(mxcmci_driver);
 MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver");
 MODULE_AUTHOR("Sascha Hauer, Pengutronix");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:imx-mmc");
+MODULE_ALIAS("platform:mxc-mmc");
index 80d1e6d..206fe49 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/module.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/stmp_device.h>
-#include <linux/mmc/mxs-mmc.h>
 #include <linux/spi/mxs-spi.h>
 
 #define DRIVER_NAME    "mxs-mmc"
@@ -593,13 +592,13 @@ static int mxs_mmc_probe(struct platform_device *pdev)
        struct mxs_mmc_host *host;
        struct mmc_host *mmc;
        struct resource *iores, *dmares;
-       struct mxs_mmc_platform_data *pdata;
        struct pinctrl *pinctrl;
        int ret = 0, irq_err, irq_dma;
        dma_cap_mask_t mask;
        struct regulator *reg_vmmc;
        enum of_gpio_flags flags;
        struct mxs_ssp *ssp;
+       u32 bus_width = 0;
 
        iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
@@ -682,25 +681,15 @@ static int mxs_mmc_probe(struct platform_device *pdev)
        mmc->caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED |
                    MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL;
 
-       pdata = mmc_dev(host->mmc)->platform_data;
-       if (!pdata) {
-               u32 bus_width = 0;
-               of_property_read_u32(np, "bus-width", &bus_width);
-               if (bus_width == 4)
-                       mmc->caps |= MMC_CAP_4_BIT_DATA;
-               else if (bus_width == 8)
-                       mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
-               host->wp_gpio = of_get_named_gpio_flags(np, "wp-gpios", 0,
-                                                       &flags);
-               if (flags & OF_GPIO_ACTIVE_LOW)
-                       host->wp_inverted = 1;
-       } else {
-               if (pdata->flags & SLOTF_8_BIT_CAPABLE)
-                       mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
-               if (pdata->flags & SLOTF_4_BIT_CAPABLE)
-                       mmc->caps |= MMC_CAP_4_BIT_DATA;
-               host->wp_gpio = pdata->wp_gpio;
-       }
+       of_property_read_u32(np, "bus-width", &bus_width);
+       if (bus_width == 4)
+               mmc->caps |= MMC_CAP_4_BIT_DATA;
+       else if (bus_width == 8)
+               mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
+       host->wp_gpio = of_get_named_gpio_flags(np, "wp-gpios", 0, &flags);
+
+       if (flags & OF_GPIO_ACTIVE_LOW)
+               host->wp_inverted = 1;
 
        mmc->f_min = 400000;
        mmc->f_max = 288000000;
index 54bfd0c..d0a912f 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/pm_runtime.h>
 #include <mach/hardware.h>
 #include <plat/mmc.h>
@@ -62,6 +63,7 @@
 
 #define VS18                   (1 << 26)
 #define VS30                   (1 << 25)
+#define HSS                    (1 << 21)
 #define SDVS18                 (0x5 << 9)
 #define SDVS30                 (0x6 << 9)
 #define SDVS33                 (0x7 << 9)
 #define CLKD_SHIFT             6
 #define DTO_MASK               0x000F0000
 #define DTO_SHIFT              16
-#define INT_EN_MASK            0x307F0033
-#define BWR_ENABLE             (1 << 4)
-#define BRR_ENABLE             (1 << 5)
-#define DTO_ENABLE             (1 << 20)
 #define INIT_STREAM            (1 << 1)
 #define DP_SELECT              (1 << 21)
 #define DDIR                   (1 << 4)
-#define DMA_EN                 0x1
+#define DMAE                   0x1
 #define MSBS                   (1 << 5)
 #define BCE                    (1 << 1)
 #define FOUR_BIT               (1 << 1)
+#define HSPE                   (1 << 2)
 #define DDR                    (1 << 19)
 #define DW8                    (1 << 5)
-#define CC                     0x1
-#define TC                     0x02
 #define OD                     0x1
-#define ERR                    (1 << 15)
-#define CMD_TIMEOUT            (1 << 16)
-#define DATA_TIMEOUT           (1 << 20)
-#define CMD_CRC                        (1 << 17)
-#define DATA_CRC               (1 << 21)
-#define CARD_ERR               (1 << 28)
 #define STAT_CLEAR             0xFFFFFFFF
 #define INIT_STREAM_CMD                0x00000000
 #define DUAL_VOLT_OCR_BIT      7
 #define SOFTRESET              (1 << 1)
 #define RESETDONE              (1 << 0)
 
+/* Interrupt masks for IE and ISE register */
+#define CC_EN                  (1 << 0)
+#define TC_EN                  (1 << 1)
+#define BWR_EN                 (1 << 4)
+#define BRR_EN                 (1 << 5)
+#define ERR_EN                 (1 << 15)
+#define CTO_EN                 (1 << 16)
+#define CCRC_EN                        (1 << 17)
+#define CEB_EN                 (1 << 18)
+#define CIE_EN                 (1 << 19)
+#define DTO_EN                 (1 << 20)
+#define DCRC_EN                        (1 << 21)
+#define DEB_EN                 (1 << 22)
+#define CERR_EN                        (1 << 28)
+#define BADA_EN                        (1 << 29)
+
+#define INT_EN_MASK            (BADA_EN | CERR_EN | DEB_EN | DCRC_EN |\
+               DTO_EN | CIE_EN | CEB_EN | CCRC_EN | CTO_EN | \
+               BRR_EN | BWR_EN | TC_EN | CC_EN)
+
 #define MMC_AUTOSUSPEND_DELAY  100
 #define MMC_TIMEOUT_MS         20
 #define OMAP_MMC_MIN_CLOCK     400000
@@ -178,7 +189,8 @@ struct omap_hsmmc_host {
 
 static int omap_hsmmc_card_detect(struct device *dev, int slot)
 {
-       struct omap_mmc_platform_data *mmc = dev->platform_data;
+       struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+       struct omap_mmc_platform_data *mmc = host->pdata;
 
        /* NOTE: assumes card detect signal is active-low */
        return !gpio_get_value_cansleep(mmc->slots[0].switch_pin);
@@ -186,7 +198,8 @@ static int omap_hsmmc_card_detect(struct device *dev, int slot)
 
 static int omap_hsmmc_get_wp(struct device *dev, int slot)
 {
-       struct omap_mmc_platform_data *mmc = dev->platform_data;
+       struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+       struct omap_mmc_platform_data *mmc = host->pdata;
 
        /* NOTE: assumes write protect signal is active-high */
        return gpio_get_value_cansleep(mmc->slots[0].gpio_wp);
@@ -194,7 +207,8 @@ static int omap_hsmmc_get_wp(struct device *dev, int slot)
 
 static int omap_hsmmc_get_cover_state(struct device *dev, int slot)
 {
-       struct omap_mmc_platform_data *mmc = dev->platform_data;
+       struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+       struct omap_mmc_platform_data *mmc = host->pdata;
 
        /* NOTE: assumes card detect signal is active-low */
        return !gpio_get_value_cansleep(mmc->slots[0].switch_pin);
@@ -204,7 +218,8 @@ static int omap_hsmmc_get_cover_state(struct device *dev, int slot)
 
 static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot)
 {
-       struct omap_mmc_platform_data *mmc = dev->platform_data;
+       struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+       struct omap_mmc_platform_data *mmc = host->pdata;
 
        disable_irq(mmc->slots[0].card_detect_irq);
        return 0;
@@ -212,7 +227,8 @@ static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot)
 
 static int omap_hsmmc_resume_cdirq(struct device *dev, int slot)
 {
-       struct omap_mmc_platform_data *mmc = dev->platform_data;
+       struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+       struct omap_mmc_platform_data *mmc = host->pdata;
 
        enable_irq(mmc->slots[0].card_detect_irq);
        return 0;
@@ -297,7 +313,7 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
 
        reg = regulator_get(host->dev, "vmmc");
        if (IS_ERR(reg)) {
-               dev_dbg(host->dev, "vmmc regulator missing\n");
+               dev_err(host->dev, "vmmc regulator missing\n");
                return PTR_ERR(reg);
        } else {
                mmc_slot(host).set_power = omap_hsmmc_set_power;
@@ -450,13 +466,13 @@ static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host,
        unsigned int irq_mask;
 
        if (host->use_dma)
-               irq_mask = INT_EN_MASK & ~(BRR_ENABLE | BWR_ENABLE);
+               irq_mask = INT_EN_MASK & ~(BRR_EN | BWR_EN);
        else
                irq_mask = INT_EN_MASK;
 
        /* Disable timeout for erases */
        if (cmd->opcode == MMC_ERASE)
-               irq_mask &= ~DTO_ENABLE;
+               irq_mask &= ~DTO_EN;
 
        OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
        OMAP_HSMMC_WRITE(host->base, ISE, irq_mask);
@@ -489,6 +505,7 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
        struct mmc_ios *ios = &host->mmc->ios;
        unsigned long regval;
        unsigned long timeout;
+       unsigned long clkdiv;
 
        dev_vdbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock);
 
@@ -496,7 +513,8 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
 
        regval = OMAP_HSMMC_READ(host->base, SYSCTL);
        regval = regval & ~(CLKD_MASK | DTO_MASK);
-       regval = regval | (calc_divisor(host, ios) << 6) | (DTO << 16);
+       clkdiv = calc_divisor(host, ios);
+       regval = regval | (clkdiv << 6) | (DTO << 16);
        OMAP_HSMMC_WRITE(host->base, SYSCTL, regval);
        OMAP_HSMMC_WRITE(host->base, SYSCTL,
                OMAP_HSMMC_READ(host->base, SYSCTL) | ICE);
@@ -507,6 +525,27 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host)
                && time_before(jiffies, timeout))
                cpu_relax();
 
+       /*
+        * Enable High-Speed Support
+        * Pre-Requisites
+        *      - Controller should support High-Speed-Enable Bit
+        *      - Controller should not be using DDR Mode
+        *      - Controller should advertise that it supports High Speed
+        *        in capabilities register
+        *      - MMC/SD clock coming out of controller > 25MHz
+        */
+       if ((mmc_slot(host).features & HSMMC_HAS_HSPE_SUPPORT) &&
+           (ios->timing != MMC_TIMING_UHS_DDR50) &&
+           ((OMAP_HSMMC_READ(host->base, CAPA) & HSS) == HSS)) {
+               regval = OMAP_HSMMC_READ(host->base, HCTL);
+               if (clkdiv && (clk_get_rate(host->fclk)/clkdiv) > 25000000)
+                       regval |= HSPE;
+               else
+                       regval &= ~HSPE;
+
+               OMAP_HSMMC_WRITE(host->base, HCTL, regval);
+       }
+
        omap_hsmmc_start_clock(host);
 }
 
@@ -671,8 +710,8 @@ static void send_init_stream(struct omap_hsmmc_host *host)
        OMAP_HSMMC_WRITE(host->base, CMD, INIT_STREAM_CMD);
 
        timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS);
-       while ((reg != CC) && time_before(jiffies, timeout))
-               reg = OMAP_HSMMC_READ(host->base, STAT) & CC;
+       while ((reg != CC_EN) && time_before(jiffies, timeout))
+               reg = OMAP_HSMMC_READ(host->base, STAT) & CC_EN;
 
        OMAP_HSMMC_WRITE(host->base, CON,
                OMAP_HSMMC_READ(host->base, CON) & ~INIT_STREAM);
@@ -763,7 +802,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd,
        }
 
        if (host->use_dma)
-               cmdreg |= DMA_EN;
+               cmdreg |= DMAE;
 
        host->req_in_progress = 1;
 
@@ -963,16 +1002,20 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host,
                        __func__);
 }
 
-static void hsmmc_command_incomplete(struct omap_hsmmc_host *host, int err)
+static void hsmmc_command_incomplete(struct omap_hsmmc_host *host,
+                                       int err, int end_cmd)
 {
-       omap_hsmmc_reset_controller_fsm(host, SRC);
-       host->cmd->error = err;
+       if (end_cmd) {
+               omap_hsmmc_reset_controller_fsm(host, SRC);
+               if (host->cmd)
+                       host->cmd->error = err;
+       }
 
        if (host->data) {
                omap_hsmmc_reset_controller_fsm(host, SRD);
                omap_hsmmc_dma_cleanup(host, err);
-       }
-
+       } else if (host->mrq && host->mrq->cmd)
+               host->mrq->cmd->error = err;
 }
 
 static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
@@ -983,23 +1026,25 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
        data = host->data;
        dev_vdbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);
 
-       if (status & ERR) {
+       if (status & ERR_EN) {
                omap_hsmmc_dbg_report_irq(host, status);
-               if (status & (CMD_TIMEOUT | DATA_TIMEOUT))
-                       hsmmc_command_incomplete(host, -ETIMEDOUT);
-               else if (status & (CMD_CRC | DATA_CRC))
-                       hsmmc_command_incomplete(host, -EILSEQ);
 
-               end_cmd = 1;
+               if (status & (CTO_EN | CCRC_EN))
+                       end_cmd = 1;
+               if (status & (CTO_EN | DTO_EN))
+                       hsmmc_command_incomplete(host, -ETIMEDOUT, end_cmd);
+               else if (status & (CCRC_EN | DCRC_EN))
+                       hsmmc_command_incomplete(host, -EILSEQ, end_cmd);
+
                if (host->data || host->response_busy) {
-                       end_trans = 1;
+                       end_trans = !end_cmd;
                        host->response_busy = 0;
                }
        }
 
-       if (end_cmd || ((status & CC) && host->cmd))
+       if (end_cmd || ((status & CC_EN) && host->cmd))
                omap_hsmmc_cmd_done(host, host->cmd);
-       if ((end_trans || (status & TC)) && host->mrq)
+       if ((end_trans || (status & TC_EN)) && host->mrq)
                omap_hsmmc_xfer_done(host, data);
 }
 
@@ -1096,7 +1141,7 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd)
 
        return 0;
 err:
-       dev_dbg(mmc_dev(host->mmc), "Unable to switch operating voltage\n");
+       dev_err(mmc_dev(host->mmc), "Unable to switch operating voltage\n");
        return ret;
 }
 
@@ -1355,7 +1400,7 @@ omap_hsmmc_prepare_data(struct omap_hsmmc_host *host, struct mmc_request *req)
        if (host->use_dma) {
                ret = omap_hsmmc_start_dma_transfer(host, req);
                if (ret != 0) {
-                       dev_dbg(mmc_dev(host->mmc), "MMC start dma failure\n");
+                       dev_err(mmc_dev(host->mmc), "MMC start dma failure\n");
                        return ret;
                }
        }
@@ -1673,7 +1718,7 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
 {
        struct omap_mmc_platform_data *pdata;
        struct device_node *np = dev->of_node;
-       u32 bus_width;
+       u32 bus_width, max_freq;
 
        pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata)
@@ -1700,6 +1745,12 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
        if (of_find_property(np, "ti,needs-special-reset", NULL))
                pdata->slots[0].features |= HSMMC_HAS_UPDATED_RESET;
 
+       if (!of_property_read_u32(np, "max-frequency", &max_freq))
+               pdata->max_freq = max_freq;
+
+       if (of_find_property(np, "ti,needs-special-hs-handling", NULL))
+               pdata->slots[0].features |= HSMMC_HAS_HSPE_SUPPORT;
+
        return pdata;
 }
 #else
@@ -1720,6 +1771,7 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
        const struct of_device_id *match;
        dma_cap_mask_t mask;
        unsigned tx_req, rx_req;
+       struct pinctrl *pinctrl;
 
        match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev);
        if (match) {
@@ -1816,7 +1868,6 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
         * MMC can still work without debounce clock.
         */
        if (IS_ERR(host->dbclk)) {
-               dev_warn(mmc_dev(host->mmc), "Failed to get debounce clk\n");
                host->dbclk = NULL;
        } else if (clk_prepare_enable(host->dbclk) != 0) {
                dev_warn(mmc_dev(host->mmc), "Failed to enable debounce clk\n");
@@ -1884,13 +1935,13 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
        ret = request_irq(host->irq, omap_hsmmc_irq, 0,
                        mmc_hostname(mmc), host);
        if (ret) {
-               dev_dbg(mmc_dev(host->mmc), "Unable to grab HSMMC IRQ\n");
+               dev_err(mmc_dev(host->mmc), "Unable to grab HSMMC IRQ\n");
                goto err_irq;
        }
 
        if (pdata->init != NULL) {
                if (pdata->init(&pdev->dev) != 0) {
-                       dev_dbg(mmc_dev(host->mmc),
+                       dev_err(mmc_dev(host->mmc),
                                "Unable to configure MMC IRQs\n");
                        goto err_irq_cd_init;
                }
@@ -1913,7 +1964,7 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
                                           IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
                                           mmc_hostname(mmc), host);
                if (ret) {
-                       dev_dbg(mmc_dev(host->mmc),
+                       dev_err(mmc_dev(host->mmc),
                                "Unable to grab MMC CD IRQ\n");
                        goto err_irq_cd;
                }
@@ -1923,6 +1974,11 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
 
        omap_hsmmc_disable_irq(host);
 
+       pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+       if (IS_ERR(pinctrl))
+               dev_warn(&pdev->dev,
+                       "pins are not configured from the driver\n");
+
        omap_hsmmc_protect_card(host);
 
        mmc_add_host(mmc);
@@ -2009,9 +2065,9 @@ static int __devexit omap_hsmmc_remove(struct platform_device *pdev)
                clk_put(host->dbclk);
        }
 
-       mmc_free_host(host->mmc);
+       omap_hsmmc_gpio_free(host->pdata);
        iounmap(host->base);
-       omap_hsmmc_gpio_free(pdev->dev.platform_data);
+       mmc_free_host(host->mmc);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (res)
@@ -2022,6 +2078,25 @@ static int __devexit omap_hsmmc_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM
+static int omap_hsmmc_prepare(struct device *dev)
+{
+       struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+
+       if (host->pdata->suspend)
+               return host->pdata->suspend(dev, host->slot_id);
+
+       return 0;
+}
+
+static void omap_hsmmc_complete(struct device *dev)
+{
+       struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+
+       if (host->pdata->resume)
+               host->pdata->resume(dev, host->slot_id);
+
+}
+
 static int omap_hsmmc_suspend(struct device *dev)
 {
        int ret = 0;
@@ -2035,23 +2110,10 @@ static int omap_hsmmc_suspend(struct device *dev)
 
        pm_runtime_get_sync(host->dev);
        host->suspended = 1;
-       if (host->pdata->suspend) {
-               ret = host->pdata->suspend(dev, host->slot_id);
-               if (ret) {
-                       dev_dbg(dev, "Unable to handle MMC board"
-                                       " level suspend\n");
-                       host->suspended = 0;
-                       return ret;
-               }
-       }
        ret = mmc_suspend_host(host->mmc);
 
        if (ret) {
                host->suspended = 0;
-               if (host->pdata->resume) {
-                       if (host->pdata->resume(dev, host->slot_id))
-                               dev_dbg(dev, "Unmask interrupt failed\n");
-               }
                goto err;
        }
 
@@ -2088,12 +2150,6 @@ static int omap_hsmmc_resume(struct device *dev)
        if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER))
                omap_hsmmc_conf_bus_power(host);
 
-       if (host->pdata->resume) {
-               ret = host->pdata->resume(dev, host->slot_id);
-               if (ret)
-                       dev_dbg(dev, "Unmask interrupt failed\n");
-       }
-
        omap_hsmmc_protect_card(host);
 
        /* Notify the core to resume the host */
@@ -2109,8 +2165,10 @@ static int omap_hsmmc_resume(struct device *dev)
 }
 
 #else
+#define omap_hsmmc_prepare     NULL
+#define omap_hsmmc_complete    NULL
 #define omap_hsmmc_suspend     NULL
-#define omap_hsmmc_resume              NULL
+#define omap_hsmmc_resume      NULL
 #endif
 
 static int omap_hsmmc_runtime_suspend(struct device *dev)
@@ -2138,6 +2196,8 @@ static int omap_hsmmc_runtime_resume(struct device *dev)
 static struct dev_pm_ops omap_hsmmc_dev_pm_ops = {
        .suspend        = omap_hsmmc_suspend,
        .resume         = omap_hsmmc_resume,
+       .prepare        = omap_hsmmc_prepare,
+       .complete       = omap_hsmmc_complete,
        .runtime_suspend = omap_hsmmc_runtime_suspend,
        .runtime_resume = omap_hsmmc_runtime_resume,
 };
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
new file mode 100644 (file)
index 0000000..12b0a78
--- /dev/null
@@ -0,0 +1,312 @@
+/*
+ * Secure Digital Host Controller Interface ACPI driver.
+ *
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * 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.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/compiler.h>
+#include <linux/stddef.h>
+#include <linux/bitops.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/acpi.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/pm.h>
+#include <linux/mmc/sdhci.h>
+
+#include "sdhci.h"
+
+enum {
+       SDHCI_ACPI_SD_CD        = BIT(0),
+       SDHCI_ACPI_RUNTIME_PM   = BIT(1),
+};
+
+struct sdhci_acpi_chip {
+       const struct    sdhci_ops *ops;
+       unsigned int    quirks;
+       unsigned int    quirks2;
+       unsigned long   caps;
+       unsigned int    caps2;
+       mmc_pm_flag_t   pm_caps;
+};
+
+struct sdhci_acpi_slot {
+       const struct    sdhci_acpi_chip *chip;
+       unsigned int    quirks;
+       unsigned int    quirks2;
+       unsigned long   caps;
+       unsigned int    caps2;
+       mmc_pm_flag_t   pm_caps;
+       unsigned int    flags;
+};
+
+struct sdhci_acpi_host {
+       struct sdhci_host               *host;
+       const struct sdhci_acpi_slot    *slot;
+       struct platform_device          *pdev;
+       bool                            use_runtime_pm;
+};
+
+static inline bool sdhci_acpi_flag(struct sdhci_acpi_host *c, unsigned int flag)
+{
+       return c->slot && (c->slot->flags & flag);
+}
+
+static int sdhci_acpi_enable_dma(struct sdhci_host *host)
+{
+       return 0;
+}
+
+static const struct sdhci_ops sdhci_acpi_ops_dflt = {
+       .enable_dma = sdhci_acpi_enable_dma,
+};
+
+static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = {
+       .quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON,
+       .caps    = MMC_CAP_NONREMOVABLE | MMC_CAP_POWER_OFF_CARD,
+       .flags   = SDHCI_ACPI_RUNTIME_PM,
+       .pm_caps = MMC_PM_KEEP_POWER,
+};
+
+static const struct acpi_device_id sdhci_acpi_ids[] = {
+       { "INT33C6", (kernel_ulong_t)&sdhci_acpi_slot_int_sdio },
+       { "PNP0D40" },
+       { },
+};
+MODULE_DEVICE_TABLE(acpi, sdhci_acpi_ids);
+
+static const struct sdhci_acpi_slot *sdhci_acpi_get_slot(const char *hid)
+{
+       const struct acpi_device_id *id;
+
+       for (id = sdhci_acpi_ids; id->id[0]; id++)
+               if (!strcmp(id->id, hid))
+                       return (const struct sdhci_acpi_slot *)id->driver_data;
+       return NULL;
+}
+
+static int __devinit sdhci_acpi_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       acpi_handle handle = ACPI_HANDLE(dev);
+       struct acpi_device *device;
+       struct sdhci_acpi_host *c;
+       struct sdhci_host *host;
+       struct resource *iomem;
+       resource_size_t len;
+       const char *hid;
+       int err;
+
+       if (acpi_bus_get_device(handle, &device))
+               return -ENODEV;
+
+       if (acpi_bus_get_status(device) || !device->status.present)
+               return -ENODEV;
+
+       hid = acpi_device_hid(device);
+
+       iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!iomem)
+               return -ENOMEM;
+
+       len = resource_size(iomem);
+       if (len < 0x100)
+               dev_err(dev, "Invalid iomem size!\n");
+
+       if (!devm_request_mem_region(dev, iomem->start, len, dev_name(dev)))
+               return -ENOMEM;
+
+       host = sdhci_alloc_host(dev, sizeof(struct sdhci_acpi_host));
+       if (IS_ERR(host))
+               return PTR_ERR(host);
+
+       c = sdhci_priv(host);
+       c->host = host;
+       c->slot = sdhci_acpi_get_slot(hid);
+       c->pdev = pdev;
+       c->use_runtime_pm = sdhci_acpi_flag(c, SDHCI_ACPI_RUNTIME_PM);
+
+       platform_set_drvdata(pdev, c);
+
+       host->hw_name   = "ACPI";
+       host->ops       = &sdhci_acpi_ops_dflt;
+       host->irq       = platform_get_irq(pdev, 0);
+
+       host->ioaddr = devm_ioremap_nocache(dev, iomem->start,
+                                           resource_size(iomem));
+       if (host->ioaddr == NULL) {
+               err = -ENOMEM;
+               goto err_free;
+       }
+
+       if (!dev->dma_mask) {
+               u64 dma_mask;
+
+               if (sdhci_readl(host, SDHCI_CAPABILITIES) & SDHCI_CAN_64BIT) {
+                       /* 64-bit DMA is not supported at present */
+                       dma_mask = DMA_BIT_MASK(32);
+               } else {
+                       dma_mask = DMA_BIT_MASK(32);
+               }
+
+               dev->dma_mask = &dev->coherent_dma_mask;
+               dev->coherent_dma_mask = dma_mask;
+       }
+
+       if (c->slot) {
+               if (c->slot->chip) {
+                       host->ops            = c->slot->chip->ops;
+                       host->quirks        |= c->slot->chip->quirks;
+                       host->quirks2       |= c->slot->chip->quirks2;
+                       host->mmc->caps     |= c->slot->chip->caps;
+                       host->mmc->caps2    |= c->slot->chip->caps2;
+                       host->mmc->pm_caps  |= c->slot->chip->pm_caps;
+               }
+               host->quirks        |= c->slot->quirks;
+               host->quirks2       |= c->slot->quirks2;
+               host->mmc->caps     |= c->slot->caps;
+               host->mmc->caps2    |= c->slot->caps2;
+               host->mmc->pm_caps  |= c->slot->pm_caps;
+       }
+
+       err = sdhci_add_host(host);
+       if (err)
+               goto err_free;
+
+       if (c->use_runtime_pm) {
+               pm_suspend_ignore_children(dev, 1);
+               pm_runtime_set_autosuspend_delay(dev, 50);
+               pm_runtime_use_autosuspend(dev);
+               pm_runtime_enable(dev);
+       }
+
+       return 0;
+
+err_free:
+       platform_set_drvdata(pdev, NULL);
+       sdhci_free_host(c->host);
+       return err;
+}
+
+static int __devexit sdhci_acpi_remove(struct platform_device *pdev)
+{
+       struct sdhci_acpi_host *c = platform_get_drvdata(pdev);
+       struct device *dev = &pdev->dev;
+       int dead;
+
+       if (c->use_runtime_pm) {
+               pm_runtime_get_sync(dev);
+               pm_runtime_disable(dev);
+               pm_runtime_put_noidle(dev);
+       }
+
+       dead = (sdhci_readl(c->host, SDHCI_INT_STATUS) == ~0);
+       sdhci_remove_host(c->host, dead);
+       platform_set_drvdata(pdev, NULL);
+       sdhci_free_host(c->host);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+
+static int sdhci_acpi_suspend(struct device *dev)
+{
+       struct sdhci_acpi_host *c = dev_get_drvdata(dev);
+
+       return sdhci_suspend_host(c->host);
+}
+
+static int sdhci_acpi_resume(struct device *dev)
+{
+       struct sdhci_acpi_host *c = dev_get_drvdata(dev);
+
+       return sdhci_resume_host(c->host);
+}
+
+#else
+
+#define sdhci_acpi_suspend     NULL
+#define sdhci_acpi_resume      NULL
+
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+
+static int sdhci_acpi_runtime_suspend(struct device *dev)
+{
+       struct sdhci_acpi_host *c = dev_get_drvdata(dev);
+
+       return sdhci_runtime_suspend_host(c->host);
+}
+
+static int sdhci_acpi_runtime_resume(struct device *dev)
+{
+       struct sdhci_acpi_host *c = dev_get_drvdata(dev);
+
+       return sdhci_runtime_resume_host(c->host);
+}
+
+static int sdhci_acpi_runtime_idle(struct device *dev)
+{
+       return 0;
+}
+
+#else
+
+#define sdhci_acpi_runtime_suspend     NULL
+#define sdhci_acpi_runtime_resume      NULL
+#define sdhci_acpi_runtime_idle                NULL
+
+#endif
+
+static const struct dev_pm_ops sdhci_acpi_pm_ops = {
+       .suspend                = sdhci_acpi_suspend,
+       .resume                 = sdhci_acpi_resume,
+       .runtime_suspend        = sdhci_acpi_runtime_suspend,
+       .runtime_resume         = sdhci_acpi_runtime_resume,
+       .runtime_idle           = sdhci_acpi_runtime_idle,
+};
+
+static struct platform_driver sdhci_acpi_driver = {
+       .driver = {
+               .name                   = "sdhci-acpi",
+               .owner                  = THIS_MODULE,
+               .acpi_match_table       = sdhci_acpi_ids,
+               .pm                     = &sdhci_acpi_pm_ops,
+       },
+       .probe  = sdhci_acpi_probe,
+       .remove = __devexit_p(sdhci_acpi_remove),
+};
+
+module_platform_driver(sdhci_acpi_driver);
+
+MODULE_DESCRIPTION("Secure Digital Host Controller Interface ACPI driver");
+MODULE_AUTHOR("Adrian Hunter");
+MODULE_LICENSE("GPL v2");
index 90140eb..e621448 100644 (file)
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/err.h>
-#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
 #include <linux/mmc/host.h>
+#include <linux/module.h>
 #include <linux/of.h>
+#include <linux/of_gpio.h>
 
 #include "sdhci-pltfm.h"
 
 struct sdhci_dove_priv {
        struct clk *clk;
+       int gpio_cd;
 };
 
+static irqreturn_t sdhci_dove_carddetect_irq(int irq, void *data)
+{
+       struct sdhci_host *host = data;
+
+       tasklet_schedule(&host->card_tasklet);
+       return IRQ_HANDLED;
+}
+
 static u16 sdhci_dove_readw(struct sdhci_host *host, int reg)
 {
        u16 ret;
@@ -49,16 +60,25 @@ static u16 sdhci_dove_readw(struct sdhci_host *host, int reg)
 
 static u32 sdhci_dove_readl(struct sdhci_host *host, int reg)
 {
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct sdhci_dove_priv *priv = pltfm_host->priv;
        u32 ret;
 
+       ret = readl(host->ioaddr + reg);
+
        switch (reg) {
        case SDHCI_CAPABILITIES:
-               ret = readl(host->ioaddr + reg);
                /* Mask the support for 3.0V */
                ret &= ~SDHCI_CAN_VDD_300;
                break;
-       default:
-               ret = readl(host->ioaddr + reg);
+       case SDHCI_PRESENT_STATE:
+               if (gpio_is_valid(priv->gpio_cd)) {
+                       if (gpio_get_value(priv->gpio_cd) == 0)
+                               ret |= SDHCI_CARD_PRESENT;
+                       else
+                               ret &= ~SDHCI_CARD_PRESENT;
+               }
+               break;
        }
        return ret;
 }
@@ -84,30 +104,77 @@ static int __devinit sdhci_dove_probe(struct platform_device *pdev)
        struct sdhci_dove_priv *priv;
        int ret;
 
-       ret = sdhci_pltfm_register(pdev, &sdhci_dove_pdata);
-       if (ret)
-               goto sdhci_dove_register_fail;
-
        priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_dove_priv),
                            GFP_KERNEL);
        if (!priv) {
                dev_err(&pdev->dev, "unable to allocate private data");
-               ret = -ENOMEM;
-               goto sdhci_dove_allocate_fail;
+               return -ENOMEM;
+       }
+
+       priv->clk = devm_clk_get(&pdev->dev, NULL);
+
+       if (pdev->dev.of_node) {
+               priv->gpio_cd = of_get_named_gpio(pdev->dev.of_node,
+                                                 "cd-gpios", 0);
+       } else {
+               priv->gpio_cd = -EINVAL;
+       }
+
+       if (gpio_is_valid(priv->gpio_cd)) {
+               ret = gpio_request(priv->gpio_cd, "sdhci-cd");
+               if (ret) {
+                       dev_err(&pdev->dev, "card detect gpio request failed: %d\n",
+                               ret);
+                       return ret;
+               }
+               gpio_direction_input(priv->gpio_cd);
+       }
+
+       host = sdhci_pltfm_init(pdev, &sdhci_dove_pdata);
+       if (IS_ERR(host)) {
+               ret = PTR_ERR(host);
+               goto err_sdhci_pltfm_init;
        }
 
-       host = platform_get_drvdata(pdev);
        pltfm_host = sdhci_priv(host);
        pltfm_host->priv = priv;
 
-       priv->clk = clk_get(&pdev->dev, NULL);
        if (!IS_ERR(priv->clk))
                clk_prepare_enable(priv->clk);
+
+       sdhci_get_of_property(pdev);
+
+       ret = sdhci_add_host(host);
+       if (ret)
+               goto err_sdhci_add;
+
+       /*
+        * We must request the IRQ after sdhci_add_host(), as the tasklet only
+        * gets setup in sdhci_add_host() and we oops.
+        */
+       if (gpio_is_valid(priv->gpio_cd)) {
+               ret = request_irq(gpio_to_irq(priv->gpio_cd),
+                                 sdhci_dove_carddetect_irq,
+                                 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+                                 mmc_hostname(host->mmc), host);
+               if (ret) {
+                       dev_err(&pdev->dev, "card detect irq request failed: %d\n",
+                               ret);
+                       goto err_request_irq;
+               }
+       }
+
        return 0;
 
-sdhci_dove_allocate_fail:
-       sdhci_pltfm_unregister(pdev);
-sdhci_dove_register_fail:
+err_request_irq:
+       sdhci_remove_host(host, 0);
+err_sdhci_add:
+       if (!IS_ERR(priv->clk))
+               clk_disable_unprepare(priv->clk);
+       sdhci_pltfm_free(pdev);
+err_sdhci_pltfm_init:
+       if (gpio_is_valid(priv->gpio_cd))
+               gpio_free(priv->gpio_cd);
        return ret;
 }
 
@@ -117,14 +184,17 @@ static int __devexit sdhci_dove_remove(struct platform_device *pdev)
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
        struct sdhci_dove_priv *priv = pltfm_host->priv;
 
-       if (priv->clk) {
-               if (!IS_ERR(priv->clk)) {
-                       clk_disable_unprepare(priv->clk);
-                       clk_put(priv->clk);
-               }
-               devm_kfree(&pdev->dev, priv->clk);
+       sdhci_pltfm_unregister(pdev);
+
+       if (gpio_is_valid(priv->gpio_cd)) {
+               free_irq(gpio_to_irq(priv->gpio_cd), host);
+               gpio_free(priv->gpio_cd);
        }
-       return sdhci_pltfm_unregister(pdev);
+
+       if (!IS_ERR(priv->clk))
+               clk_disable_unprepare(priv->clk);
+
+       return 0;
 }
 
 static const struct of_device_id sdhci_dove_of_match_table[] __devinitdata = {
index effc2ac..1849461 100644 (file)
@@ -456,10 +456,10 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
 
        pltfm_host = sdhci_priv(host);
 
-       imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL);
+       imx_data = devm_kzalloc(&pdev->dev, sizeof(*imx_data), GFP_KERNEL);
        if (!imx_data) {
                err = -ENOMEM;
-               goto err_imx_data;
+               goto free_sdhci;
        }
 
        if (of_id)
@@ -470,19 +470,19 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
        imx_data->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
        if (IS_ERR(imx_data->clk_ipg)) {
                err = PTR_ERR(imx_data->clk_ipg);
-               goto err_clk_get;
+               goto free_sdhci;
        }
 
        imx_data->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
        if (IS_ERR(imx_data->clk_ahb)) {
                err = PTR_ERR(imx_data->clk_ahb);
-               goto err_clk_get;
+               goto free_sdhci;
        }
 
        imx_data->clk_per = devm_clk_get(&pdev->dev, "per");
        if (IS_ERR(imx_data->clk_per)) {
                err = PTR_ERR(imx_data->clk_per);
-               goto err_clk_get;
+               goto free_sdhci;
        }
 
        pltfm_host->clk = imx_data->clk_per;
@@ -494,7 +494,7 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
        imx_data->pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
        if (IS_ERR(imx_data->pinctrl)) {
                err = PTR_ERR(imx_data->pinctrl);
-               goto pin_err;
+               goto disable_clk;
        }
 
        host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
@@ -519,7 +519,7 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
                if (!host->mmc->parent->platform_data) {
                        dev_err(mmc_dev(host->mmc), "no board data!\n");
                        err = -EINVAL;
-                       goto no_board_data;
+                       goto disable_clk;
                }
                imx_data->boarddata = *((struct esdhc_platform_data *)
                                        host->mmc->parent->platform_data);
@@ -527,7 +527,8 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
 
        /* write_protect */
        if (boarddata->wp_type == ESDHC_WP_GPIO) {
-               err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
+               err = devm_gpio_request_one(&pdev->dev, boarddata->wp_gpio,
+                                           GPIOF_IN, "ESDHC_WP");
                if (err) {
                        dev_warn(mmc_dev(host->mmc),
                                 "no write-protect pin available!\n");
@@ -543,19 +544,21 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
 
        switch (boarddata->cd_type) {
        case ESDHC_CD_GPIO:
-               err = gpio_request_one(boarddata->cd_gpio, GPIOF_IN, "ESDHC_CD");
+               err = devm_gpio_request_one(&pdev->dev, boarddata->cd_gpio,
+                                           GPIOF_IN, "ESDHC_CD");
                if (err) {
                        dev_err(mmc_dev(host->mmc),
                                "no card-detect pin available!\n");
-                       goto no_card_detect_pin;
+                       goto disable_clk;
                }
 
-               err = request_irq(gpio_to_irq(boarddata->cd_gpio), cd_irq,
+               err = devm_request_irq(&pdev->dev,
+                                gpio_to_irq(boarddata->cd_gpio), cd_irq,
                                 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
                                 mmc_hostname(host->mmc), host);
                if (err) {
                        dev_err(mmc_dev(host->mmc), "request irq error\n");
-                       goto no_card_detect_irq;
+                       goto disable_clk;
                }
                /* fall through */
 
@@ -574,27 +577,15 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
 
        err = sdhci_add_host(host);
        if (err)
-               goto err_add_host;
+               goto disable_clk;
 
        return 0;
 
-err_add_host:
-       if (gpio_is_valid(boarddata->cd_gpio))
-               free_irq(gpio_to_irq(boarddata->cd_gpio), host);
-no_card_detect_irq:
-       if (gpio_is_valid(boarddata->cd_gpio))
-               gpio_free(boarddata->cd_gpio);
-       if (gpio_is_valid(boarddata->wp_gpio))
-               gpio_free(boarddata->wp_gpio);
-no_card_detect_pin:
-no_board_data:
-pin_err:
+disable_clk:
        clk_disable_unprepare(imx_data->clk_per);
        clk_disable_unprepare(imx_data->clk_ipg);
        clk_disable_unprepare(imx_data->clk_ahb);
-err_clk_get:
-       kfree(imx_data);
-err_imx_data:
+free_sdhci:
        sdhci_pltfm_free(pdev);
        return err;
 }
@@ -604,25 +595,14 @@ static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev)
        struct sdhci_host *host = platform_get_drvdata(pdev);
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
        struct pltfm_imx_data *imx_data = pltfm_host->priv;
-       struct esdhc_platform_data *boarddata = &imx_data->boarddata;
        int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
 
        sdhci_remove_host(host, dead);
 
-       if (gpio_is_valid(boarddata->wp_gpio))
-               gpio_free(boarddata->wp_gpio);
-
-       if (gpio_is_valid(boarddata->cd_gpio)) {
-               free_irq(gpio_to_irq(boarddata->cd_gpio), host);
-               gpio_free(boarddata->cd_gpio);
-       }
-
        clk_disable_unprepare(imx_data->clk_per);
        clk_disable_unprepare(imx_data->clk_ipg);
        clk_disable_unprepare(imx_data->clk_ahb);
 
-       kfree(imx_data);
-
        sdhci_pltfm_free(pdev);
 
        return 0;
index ae5fcbf..60de2ee 100644 (file)
@@ -22,6 +22,7 @@
 #include "sdhci-esdhc.h"
 
 #define VENDOR_V_22    0x12
+#define VENDOR_V_23    0x13
 static u32 esdhc_readl(struct sdhci_host *host, int reg)
 {
        u32 ret;
@@ -85,6 +86,18 @@ static u8 esdhc_readb(struct sdhci_host *host, int reg)
        return ret;
 }
 
+static void esdhc_writel(struct sdhci_host *host, u32 val, int reg)
+{
+       /*
+        * Enable IRQSTATEN[BGESEN] is just to set IRQSTAT[BGE]
+        * when SYSCTL[RSTD]) is set for some special operations.
+        * No any impact other operation.
+        */
+       if (reg == SDHCI_INT_ENABLE)
+               val |= SDHCI_INT_BLK_GAP;
+       sdhci_be32bs_writel(host, val, reg);
+}
+
 static void esdhc_writew(struct sdhci_host *host, u16 val, int reg)
 {
        if (reg == SDHCI_BLOCK_SIZE) {
@@ -121,6 +134,41 @@ static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg)
        sdhci_be32bs_writeb(host, val, reg);
 }
 
+/*
+ * For Abort or Suspend after Stop at Block Gap, ignore the ADMA
+ * error(IRQSTAT[ADMAE]) if both Transfer Complete(IRQSTAT[TC])
+ * and Block Gap Event(IRQSTAT[BGE]) are also set.
+ * For Continue, apply soft reset for data(SYSCTL[RSTD]);
+ * and re-issue the entire read transaction from beginning.
+ */
+static void esdhci_of_adma_workaround(struct sdhci_host *host, u32 intmask)
+{
+       u32 tmp;
+       bool applicable;
+       dma_addr_t dmastart;
+       dma_addr_t dmanow;
+
+       tmp = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
+       tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
+
+       applicable = (intmask & SDHCI_INT_DATA_END) &&
+               (intmask & SDHCI_INT_BLK_GAP) &&
+               (tmp == VENDOR_V_23);
+       if (!applicable)
+               return;
+
+       host->data->error = 0;
+       dmastart = sg_dma_address(host->data->sg);
+       dmanow = dmastart + host->data->bytes_xfered;
+       /*
+        * Force update to the next DMA block boundary.
+        */
+       dmanow = (dmanow & ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1)) +
+               SDHCI_DEFAULT_BOUNDARY_SIZE;
+       host->data->bytes_xfered = dmanow - dmastart;
+       sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS);
+}
+
 static int esdhc_of_enable_dma(struct sdhci_host *host)
 {
        setbits32(host->ioaddr + ESDHC_DMA_SYSCTL, ESDHC_DMA_SNOOP);
@@ -169,21 +217,36 @@ static void esdhc_of_resume(struct sdhci_host *host)
 }
 #endif
 
+static void esdhc_of_platform_init(struct sdhci_host *host)
+{
+       u32 vvn;
+
+       vvn = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
+       vvn = (vvn & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
+       if (vvn == VENDOR_V_22)
+               host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23;
+
+       if (vvn > VENDOR_V_22)
+               host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
+}
+
 static struct sdhci_ops sdhci_esdhc_ops = {
        .read_l = esdhc_readl,
        .read_w = esdhc_readw,
        .read_b = esdhc_readb,
-       .write_l = sdhci_be32bs_writel,
+       .write_l = esdhc_writel,
        .write_w = esdhc_writew,
        .write_b = esdhc_writeb,
        .set_clock = esdhc_of_set_clock,
        .enable_dma = esdhc_of_enable_dma,
        .get_max_clock = esdhc_of_get_max_clock,
        .get_min_clock = esdhc_of_get_min_clock,
+       .platform_init = esdhc_of_platform_init,
 #ifdef CONFIG_PM
        .platform_suspend = esdhc_of_suspend,
        .platform_resume = esdhc_of_resume,
 #endif
+       .adma_workaround = esdhci_of_adma_workaround,
 };
 
 static struct sdhci_pltfm_data sdhci_esdhc_pdata = {
index 4bb74b0..0777fad 100644 (file)
@@ -114,6 +114,7 @@ static int ricoh_mmc_probe_slot(struct sdhci_pci_slot *slot)
 
                SDHCI_TIMEOUT_CLK_UNIT |
                SDHCI_CAN_VDD_330 |
+               SDHCI_CAN_DO_HISPD |
                SDHCI_CAN_DO_SDMA;
        return 0;
 }
@@ -1196,7 +1197,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
                return ERR_PTR(-ENODEV);
        }
 
-       if (pci_resource_len(pdev, bar) != 0x100) {
+       if (pci_resource_len(pdev, bar) < 0x100) {
                dev_err(&pdev->dev, "Invalid iomem size. You may "
                        "experience problems.\n");
        }
index 65551a9..d4283ef 100644 (file)
@@ -78,6 +78,9 @@ void sdhci_get_of_property(struct platform_device *pdev)
                if (of_get_property(np, "broken-cd", NULL))
                        host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
 
+               if (of_get_property(np, "no-1-8-v", NULL))
+                       host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
+
                if (of_device_is_compatible(np, "fsl,p2020-rev1-esdhc"))
                        host->quirks |= SDHCI_QUIRK_BROKEN_DMA;
 
@@ -89,6 +92,12 @@ void sdhci_get_of_property(struct platform_device *pdev)
                clk = of_get_property(np, "clock-frequency", &size);
                if (clk && size == sizeof(*clk) && *clk)
                        pltfm_host->clock = be32_to_cpup(clk);
+
+               if (of_find_property(np, "keep-power-in-suspend", NULL))
+                       host->mmc->pm_caps |= MMC_PM_KEEP_POWER;
+
+               if (of_find_property(np, "enable-sdio-wakeup", NULL))
+                       host->mmc->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
        }
 }
 #else
@@ -150,6 +159,13 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
                goto err_remap;
        }
 
+       /*
+        * Some platforms need to probe the controller to be able to
+        * determine which caps should be used.
+        */
+       if (host->ops && host->ops->platform_init)
+               host->ops->platform_init(host);
+
        platform_set_drvdata(pdev, host);
 
        return host;
index e918a2b..60829c9 100644 (file)
@@ -163,10 +163,18 @@ static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
        return 0;
 }
 
+static u32 pxav3_get_max_clock(struct sdhci_host *host)
+{
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+       return clk_get_rate(pltfm_host->clk);
+}
+
 static struct sdhci_ops pxav3_sdhci_ops = {
        .platform_reset_exit = pxav3_set_private_registers,
        .set_uhs_signaling = pxav3_set_uhs_signaling,
        .platform_send_init_74_clocks = pxav3_gen_init_74_clocks,
+       .get_max_clock = pxav3_get_max_clock,
 };
 
 #ifdef CONFIG_OF
@@ -249,7 +257,8 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
 
        host->quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
                | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
-               | SDHCI_QUIRK_32BIT_ADMA_SIZE;
+               | SDHCI_QUIRK_32BIT_ADMA_SIZE
+               | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN;
 
        /* enable 1/8V DDR capable */
        host->mmc->caps |= MMC_CAP_1_8V_DDR;
@@ -271,6 +280,8 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
 
                if (pdata->quirks)
                        host->quirks |= pdata->quirks;
+               if (pdata->quirks2)
+                       host->quirks2 |= pdata->quirks2;
                if (pdata->host_caps)
                        host->mmc->caps |= pdata->host_caps;
                if (pdata->host_caps2)
index 2903949..82b7a7a 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/of_gpio.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
+#include <linux/pinctrl/consumer.h>
 
 #include <linux/mmc/host.h>
 
@@ -57,6 +58,7 @@ struct sdhci_s3c {
        int                     ext_cd_irq;
        int                     ext_cd_gpio;
        int                     *gpios;
+       struct pinctrl          *pctrl;
 
        struct clk              *clk_io;
        struct clk              *clk_bus[MAX_BUS_CLK];
@@ -211,8 +213,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);
@@ -373,18 +375,27 @@ static struct sdhci_ops sdhci_s3c_ops = {
 static void sdhci_s3c_notify_change(struct platform_device *dev, int state)
 {
        struct sdhci_host *host = platform_get_drvdata(dev);
+#ifdef CONFIG_PM_RUNTIME
+       struct sdhci_s3c *sc = sdhci_priv(host);
+#endif
        unsigned long flags;
 
        if (host) {
                spin_lock_irqsave(&host->lock, flags);
                if (state) {
                        dev_dbg(&dev->dev, "card inserted.\n");
+#ifdef CONFIG_PM_RUNTIME
+                       clk_prepare_enable(sc->clk_io);
+#endif
                        host->flags &= ~SDHCI_DEVICE_DEAD;
                        host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
                } else {
                        dev_dbg(&dev->dev, "card removed.\n");
                        host->flags |= SDHCI_DEVICE_DEAD;
                        host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+#ifdef CONFIG_PM_RUNTIME
+                       clk_disable_unprepare(sc->clk_io);
+#endif
                }
                tasklet_schedule(&host->card_tasklet);
                spin_unlock_irqrestore(&host->lock, flags);
@@ -406,7 +417,7 @@ static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc)
        struct s3c_sdhci_platdata *pdata = sc->pdata;
        struct device *dev = &sc->pdev->dev;
 
-       if (gpio_request(pdata->ext_cd_gpio, "SDHCI EXT CD") == 0) {
+       if (devm_gpio_request(dev, pdata->ext_cd_gpio, "SDHCI EXT CD") == 0) {
                sc->ext_cd_gpio = pdata->ext_cd_gpio;
                sc->ext_cd_irq = gpio_to_irq(pdata->ext_cd_gpio);
                if (sc->ext_cd_irq &&
@@ -449,12 +460,12 @@ static int __devinit sdhci_s3c_parse_dt(struct device *dev,
                return -ENOMEM;
 
        /* get the card detection method */
-       if (of_get_property(node, "broken-cd", 0)) {
+       if (of_get_property(node, "broken-cd", NULL)) {
                pdata->cd_type = S3C_SDHCI_CD_NONE;
                goto setup_bus;
        }
 
-       if (of_get_property(node, "non-removable", 0)) {
+       if (of_get_property(node, "non-removable", NULL)) {
                pdata->cd_type = S3C_SDHCI_CD_PERMANENT;
                goto setup_bus;
        }
@@ -477,8 +488,9 @@ static int __devinit sdhci_s3c_parse_dt(struct device *dev,
                return -EINVAL;
        }
 
-       dev_info(dev, "assuming no card detect line available\n");
-       pdata->cd_type = S3C_SDHCI_CD_NONE;
+       /* assuming internal card detect that will be configured by pinctrl */
+       pdata->cd_type = S3C_SDHCI_CD_INTERNAL;
+       goto setup_bus;
 
  found_cd:
        if (pdata->cd_type == S3C_SDHCI_CD_GPIO) {
@@ -487,7 +499,7 @@ static int __devinit sdhci_s3c_parse_dt(struct device *dev,
                if (of_get_property(node, "cd-inverted", NULL))
                        pdata->ext_cd_gpio_invert = 1;
        } else if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
-               ret = gpio_request(gpio, "sdhci-cd");
+               ret = devm_gpio_request(dev, gpio, "sdhci-cd");
                if (ret) {
                        dev_err(dev, "card detect gpio request failed\n");
                        return -EINVAL;
@@ -496,33 +508,28 @@ static int __devinit sdhci_s3c_parse_dt(struct device *dev,
        }
 
  setup_bus:
+       if (!IS_ERR(ourhost->pctrl))
+               return 0;
+
        /* get the gpios for command, clock and data lines */
        for (cnt = 0; cnt < NUM_GPIOS(pdata->max_width); cnt++) {
                gpio = of_get_gpio(node, cnt);
                if (!gpio_is_valid(gpio)) {
                        dev_err(dev, "invalid gpio[%d]\n", cnt);
-                       goto err_free_dt_cd_gpio;
+                       return -EINVAL;
                }
                ourhost->gpios[cnt] = gpio;
        }
 
        for (cnt = 0; cnt < NUM_GPIOS(pdata->max_width); cnt++) {
-               ret = gpio_request(ourhost->gpios[cnt], "sdhci-gpio");
+               ret = devm_gpio_request(dev, ourhost->gpios[cnt], "sdhci-gpio");
                if (ret) {
                        dev_err(dev, "gpio[%d] request failed\n", cnt);
-                       goto err_free_dt_gpios;
+                       return -EINVAL;
                }
        }
 
        return 0;
-
- err_free_dt_gpios:
-       while (--cnt >= 0)
-               gpio_free(ourhost->gpios[cnt]);
- err_free_dt_cd_gpio:
-       if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL)
-               gpio_free(ourhost->ext_cd_gpio);
-       return -EINVAL;
 }
 #else
 static int __devinit sdhci_s3c_parse_dt(struct device *dev,
@@ -579,13 +586,15 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
        pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata) {
                ret = -ENOMEM;
-               goto err_pdata;
+               goto err_pdata_io_clk;
        }
 
+       sc->pctrl = devm_pinctrl_get_select_default(&pdev->dev);
+
        if (pdev->dev.of_node) {
                ret = sdhci_s3c_parse_dt(&pdev->dev, host, pdata);
                if (ret)
-                       goto err_pdata;
+                       goto err_pdata_io_clk;
        } else {
                memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata));
                sc->ext_cd_gpio = -1; /* invalid gpio number */
@@ -603,11 +612,11 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
        if (IS_ERR(sc->clk_io)) {
                dev_err(dev, "failed to get io clock\n");
                ret = PTR_ERR(sc->clk_io);
-               goto err_io_clk;
+               goto err_pdata_io_clk;
        }
 
        /* 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 +647,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 +756,14 @@ 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);
+       if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL)
+               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,16 +772,10 @@ 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:
-       for (ptr = 0; ptr < NUM_GPIOS(sc->pdata->max_width); ptr++)
-               gpio_free(sc->gpios[ptr]);
-       if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL)
-               gpio_free(sc->ext_cd_gpio);
-
- err_pdata:
+ err_pdata_io_clk:
        sdhci_free_host(host);
 
        return ret;
@@ -790,11 +794,9 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
        if (sc->ext_cd_irq)
                free_irq(sc->ext_cd_irq, sc);
 
-       if (gpio_is_valid(sc->ext_cd_gpio))
-               gpio_free(sc->ext_cd_gpio);
-
 #ifdef CONFIG_PM_RUNTIME
-       clk_enable(sc->clk_io);
+       if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL)
+               clk_prepare_enable(sc->clk_io);
 #endif
        sdhci_remove_host(host, 1);
 
@@ -802,21 +804,16 @@ 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) {
-               for (ptr = 0; ptr < NUM_GPIOS(sc->pdata->max_width); ptr++)
-                       gpio_free(sc->gpios[ptr]);
-       }
-
        sdhci_free_host(host);
        platform_set_drvdata(pdev, NULL);
 
@@ -849,8 +846,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 +858,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 6be89c0..87a7009 100644 (file)
@@ -146,6 +146,11 @@ static int __devinit sdhci_probe(struct platform_device *pdev)
                goto put_clk;
        }
 
+       ret = clk_set_rate(sdhci->clk, 50000000);
+       if (ret)
+               dev_dbg(&pdev->dev, "Error setting desired clk, clk=%lu\n",
+                               clk_get_rate(sdhci->clk));
+
        if (np) {
                sdhci->data = sdhci_probe_config_dt(pdev);
                if (IS_ERR(sdhci->data)) {
@@ -297,7 +302,7 @@ static int sdhci_suspend(struct device *dev)
 
        ret = sdhci_suspend_host(host);
        if (!ret)
-               clk_disable_unprepare(sdhci->clk);
+               clk_disable(sdhci->clk);
 
        return ret;
 }
@@ -308,7 +313,7 @@ static int sdhci_resume(struct device *dev)
        struct spear_sdhci *sdhci = dev_get_platdata(dev);
        int ret;
 
-       ret = clk_prepare_enable(sdhci->clk);
+       ret = clk_enable(sdhci->clk);
        if (ret) {
                dev_dbg(dev, "Resume: Error enabling clock\n");
                return ret;
index 7922adb..6f0bfc0 100644 (file)
@@ -1315,16 +1315,19 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
                 */
                if ((host->flags & SDHCI_NEEDS_RETUNING) &&
                    !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) {
-                       /* eMMC uses cmd21 while sd and sdio use cmd19 */
-                       tuning_opcode = mmc->card->type == MMC_TYPE_MMC ?
-                               MMC_SEND_TUNING_BLOCK_HS200 :
-                               MMC_SEND_TUNING_BLOCK;
-                       spin_unlock_irqrestore(&host->lock, flags);
-                       sdhci_execute_tuning(mmc, tuning_opcode);
-                       spin_lock_irqsave(&host->lock, flags);
-
-                       /* Restore original mmc_request structure */
-                       host->mrq = mrq;
+                       if (mmc->card) {
+                               /* eMMC uses cmd21 but sd and sdio use cmd19 */
+                               tuning_opcode =
+                                       mmc->card->type == MMC_TYPE_MMC ?
+                                       MMC_SEND_TUNING_BLOCK_HS200 :
+                                       MMC_SEND_TUNING_BLOCK;
+                               spin_unlock_irqrestore(&host->lock, flags);
+                               sdhci_execute_tuning(mmc, tuning_opcode);
+                               spin_lock_irqsave(&host->lock, flags);
+
+                               /* Restore original mmc_request structure */
+                               host->mrq = mrq;
+                       }
                }
 
                if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23))
@@ -1615,7 +1618,7 @@ static int sdhci_do_3_3v_signal_voltage_switch(struct sdhci_host *host,
        sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
        if (host->vqmmc) {
-               ret = regulator_set_voltage(host->vqmmc, 3300000, 3300000);
+               ret = regulator_set_voltage(host->vqmmc, 2700000, 3600000);
                if (ret) {
                        pr_warning("%s: Switching to 3.3V signalling voltage "
                                   " failed\n", mmc_hostname(host->mmc));
@@ -1659,7 +1662,7 @@ static int sdhci_do_1_8v_signal_voltage_switch(struct sdhci_host *host,
                 */
                if (host->vqmmc)
                        ret = regulator_set_voltage(host->vqmmc,
-                               1800000, 1800000);
+                               1700000, 1950000);
                else
                        ret = 0;
 
@@ -1991,30 +1994,11 @@ static void sdhci_enable_preset_value(struct mmc_host *mmc, bool enable)
        sdhci_runtime_pm_put(host);
 }
 
-static const struct mmc_host_ops sdhci_ops = {
-       .request        = sdhci_request,
-       .set_ios        = sdhci_set_ios,
-       .get_ro         = sdhci_get_ro,
-       .hw_reset       = sdhci_hw_reset,
-       .enable_sdio_irq = sdhci_enable_sdio_irq,
-       .start_signal_voltage_switch    = sdhci_start_signal_voltage_switch,
-       .execute_tuning                 = sdhci_execute_tuning,
-       .enable_preset_value            = sdhci_enable_preset_value,
-};
-
-/*****************************************************************************\
- *                                                                           *
- * Tasklets                                                                  *
- *                                                                           *
-\*****************************************************************************/
-
-static void sdhci_tasklet_card(unsigned long param)
+static void sdhci_card_event(struct mmc_host *mmc)
 {
-       struct sdhci_host *host;
+       struct sdhci_host *host = mmc_priv(mmc);
        unsigned long flags;
 
-       host = (struct sdhci_host*)param;
-
        spin_lock_irqsave(&host->lock, flags);
 
        /* Check host->mrq first in case we are runtime suspended */
@@ -2033,6 +2017,31 @@ static void sdhci_tasklet_card(unsigned long param)
        }
 
        spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static const struct mmc_host_ops sdhci_ops = {
+       .request        = sdhci_request,
+       .set_ios        = sdhci_set_ios,
+       .get_ro         = sdhci_get_ro,
+       .hw_reset       = sdhci_hw_reset,
+       .enable_sdio_irq = sdhci_enable_sdio_irq,
+       .start_signal_voltage_switch    = sdhci_start_signal_voltage_switch,
+       .execute_tuning                 = sdhci_execute_tuning,
+       .enable_preset_value            = sdhci_enable_preset_value,
+       .card_event                     = sdhci_card_event,
+};
+
+/*****************************************************************************\
+ *                                                                           *
+ * Tasklets                                                                  *
+ *                                                                           *
+\*****************************************************************************/
+
+static void sdhci_tasklet_card(unsigned long param)
+{
+       struct sdhci_host *host = (struct sdhci_host*)param;
+
+       sdhci_card_event(host->mmc);
 
        mmc_detect_change(host->mmc, msecs_to_jiffies(200));
 }
@@ -2279,6 +2288,8 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
                pr_err("%s: ADMA error\n", mmc_hostname(host->mmc));
                sdhci_show_adma_error(host);
                host->data->error = -EIO;
+               if (host->ops->adma_workaround)
+                       host->ops->adma_workaround(host, intmask);
        }
 
        if (host->data->error)
@@ -2837,6 +2848,9 @@ int sdhci_add_host(struct sdhci_host *host)
        if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA))
                mmc->caps |= MMC_CAP_4_BIT_DATA;
 
+       if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23)
+               mmc->caps &= ~MMC_CAP_CMD23;
+
        if (caps[0] & SDHCI_CAN_DO_HISPD)
                mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
 
@@ -2846,13 +2860,22 @@ int sdhci_add_host(struct sdhci_host *host)
 
        /* If vqmmc regulator and no 1.8V signalling, then there's no UHS */
        host->vqmmc = regulator_get(mmc_dev(mmc), "vqmmc");
-       if (IS_ERR(host->vqmmc)) {
-               pr_info("%s: no vqmmc regulator found\n", mmc_hostname(mmc));
-               host->vqmmc = NULL;
-       }
-       else if (regulator_is_supported_voltage(host->vqmmc, 1800000, 1800000))
+       if (IS_ERR_OR_NULL(host->vqmmc)) {
+               if (PTR_ERR(host->vqmmc) < 0) {
+                       pr_info("%s: no vqmmc regulator found\n",
+                               mmc_hostname(mmc));
+                       host->vqmmc = NULL;
+               }
+       } else {
                regulator_enable(host->vqmmc);
-       else
+               if (!regulator_is_supported_voltage(host->vqmmc, 1700000,
+                       1950000))
+                       caps[1] &= ~(SDHCI_SUPPORT_SDR104 |
+                                       SDHCI_SUPPORT_SDR50 |
+                                       SDHCI_SUPPORT_DDR50);
+       }
+
+       if (host->quirks2 & SDHCI_QUIRK2_NO_1_8_V)
                caps[1] &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
                       SDHCI_SUPPORT_DDR50);
 
@@ -2904,24 +2927,24 @@ int sdhci_add_host(struct sdhci_host *host)
        ocr_avail = 0;
 
        host->vmmc = regulator_get(mmc_dev(mmc), "vmmc");
-       if (IS_ERR(host->vmmc)) {
-               pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc));
-               host->vmmc = NULL;
-       } else
-               regulator_enable(host->vmmc);
+       if (IS_ERR_OR_NULL(host->vmmc)) {
+               if (PTR_ERR(host->vmmc) < 0) {
+                       pr_info("%s: no vmmc regulator found\n",
+                               mmc_hostname(mmc));
+                       host->vmmc = NULL;
+               }
+       }
 
 #ifdef CONFIG_REGULATOR
        if (host->vmmc) {
-               ret = regulator_is_supported_voltage(host->vmmc, 3300000,
-                       3300000);
+               ret = regulator_is_supported_voltage(host->vmmc, 2700000,
+                       3600000);
                if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_330)))
                        caps[0] &= ~SDHCI_CAN_VDD_330;
-               ret = regulator_is_supported_voltage(host->vmmc, 3000000,
-                       3000000);
                if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_300)))
                        caps[0] &= ~SDHCI_CAN_VDD_300;
-               ret = regulator_is_supported_voltage(host->vmmc, 1800000,
-                       1800000);
+               ret = regulator_is_supported_voltage(host->vmmc, 1700000,
+                       1950000);
                if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_180)))
                        caps[0] &= ~SDHCI_CAN_VDD_180;
        }
index 97653ea..a6d69b7 100644 (file)
 #define SDHCI_SIGNAL_ENABLE    0x38
 #define  SDHCI_INT_RESPONSE    0x00000001
 #define  SDHCI_INT_DATA_END    0x00000002
+#define  SDHCI_INT_BLK_GAP     0x00000004
 #define  SDHCI_INT_DMA_END     0x00000008
 #define  SDHCI_INT_SPACE_AVAIL 0x00000010
 #define  SDHCI_INT_DATA_AVAIL  0x00000020
 #define  SDHCI_INT_DATA_MASK   (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \
                SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \
                SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \
-               SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR)
+               SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR | \
+               SDHCI_INT_BLK_GAP)
 #define SDHCI_INT_ALL_MASK     ((unsigned int)-1)
 
 #define SDHCI_ACMD12_ERR       0x3C
@@ -278,6 +280,8 @@ struct sdhci_ops {
        void    (*hw_reset)(struct sdhci_host *host);
        void    (*platform_suspend)(struct sdhci_host *host);
        void    (*platform_resume)(struct sdhci_host *host);
+       void    (*adma_workaround)(struct sdhci_host *host, u32 intmask);
+       void    (*platform_init)(struct sdhci_host *host);
 };
 
 #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
index 11d2bc3..ae79523 100644 (file)
@@ -1104,7 +1104,6 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
 {
        struct sh_mmcif_host *host = dev_id;
        struct mmc_request *mrq = host->mrq;
-       struct mmc_data *data = mrq->data;
 
        cancel_delayed_work_sync(&host->timeout_work);
 
@@ -1152,13 +1151,14 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
        case MMCIF_WAIT_FOR_READ_END:
        case MMCIF_WAIT_FOR_WRITE_END:
                if (host->sd_error)
-                       data->error = sh_mmcif_error_manage(host);
+                       mrq->data->error = sh_mmcif_error_manage(host);
                break;
        default:
                BUG();
        }
 
        if (host->wait_for != MMCIF_WAIT_FOR_STOP) {
+               struct mmc_data *data = mrq->data;
                if (!mrq->cmd->error && data && !data->error)
                        data->bytes_xfered =
                                data->blocks * data->blksz;
@@ -1231,10 +1231,6 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
                host->sd_error = true;
                dev_dbg(&host->pd->dev, "int err state = %08x\n", state);
        }
-       if (host->state == STATE_IDLE) {
-               dev_info(&host->pd->dev, "Spurious IRQ status 0x%x", state);
-               return IRQ_HANDLED;
-       }
        if (state & ~(INT_CMD12RBE | INT_CMD12CRE)) {
                if (!host->dma_active)
                        return IRQ_WAKE_THREAD;
@@ -1310,7 +1306,6 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
        struct sh_mmcif_plat_data *pd = pdev->dev.platform_data;
        struct resource *res;
        void __iomem *reg;
-       char clk_name[8];
 
        irq[0] = platform_get_irq(pdev, 0);
        irq[1] = platform_get_irq(pdev, 1);
@@ -1360,11 +1355,10 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
        pm_runtime_enable(&pdev->dev);
        host->power = false;
 
-       snprintf(clk_name, sizeof(clk_name), "mmc%d", pdev->id);
-       host->hclk = clk_get(&pdev->dev, clk_name);
+       host->hclk = clk_get(&pdev->dev, NULL);
        if (IS_ERR(host->hclk)) {
                ret = PTR_ERR(host->hclk);
-               dev_err(&pdev->dev, "cannot get clock \"%s\": %d\n", clk_name, ret);
+               dev_err(&pdev->dev, "cannot get clock: %d\n", ret);
                goto eclkget;
        }
        ret = sh_mmcif_clk_update(host);
@@ -1466,9 +1460,9 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, NULL);
 
+       clk_disable(host->hclk);
        mmc_free_host(host->mmc);
        pm_runtime_put_sync(&pdev->dev);
-       clk_disable(host->hclk);
        pm_runtime_disable(&pdev->dev);
 
        return 0;
index 0bdc146..d6ff853 100644 (file)
@@ -123,7 +123,6 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
        struct tmio_mmc_data *mmc_data;
        struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
        struct tmio_mmc_host *host;
-       char clk_name[8];
        int irq, ret, i = 0;
        bool multiplexed_isr = true;
 
@@ -144,11 +143,10 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
                }
        }
 
-       snprintf(clk_name, sizeof(clk_name), "sdhi%d", pdev->id);
-       priv->clk = clk_get(&pdev->dev, clk_name);
+       priv->clk = clk_get(&pdev->dev, NULL);
        if (IS_ERR(priv->clk)) {
-               dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
                ret = PTR_ERR(priv->clk);
+               dev_err(&pdev->dev, "cannot get clock: %d\n", ret);
                goto eclkget;
        }
 
@@ -250,7 +248,7 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
        dev_info(&pdev->dev, "%s base at 0x%08lx clock rate %u MHz\n",
                 mmc_hostname(host->mmc), (unsigned long)
                 (platform_get_resource(pdev, IORESOURCE_MEM, 0)->start),
-                mmc_data->hclk / 1000000);
+                host->mmc->f_max / 1000000);
 
        return ret;
 
index d5655a6..cb9f361 100644 (file)
@@ -2362,6 +2362,7 @@ error4:
 error1:
        usb_free_urb(command_out_urb);
 error0:
+       usb_put_dev(udev);
        return retval;
 }
 
diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c
new file mode 100644 (file)
index 0000000..5ba4605
--- /dev/null
@@ -0,0 +1,1029 @@
+/*
+ *  WM8505/WM8650 SD/MMC Host Controller
+ *
+ *  Copyright (C) 2010 Tony Prisk
+ *  Copyright (C) 2008 WonderMedia Technologies, Inc.
+ *
+ *  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/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_device.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+
+#include <asm/byteorder.h>
+
+
+#define DRIVER_NAME "wmt-sdhc"
+
+
+/* MMC/SD controller registers */
+#define SDMMC_CTLR                     0x00
+#define SDMMC_CMD                      0x01
+#define SDMMC_RSPTYPE                  0x02
+#define SDMMC_ARG                      0x04
+#define SDMMC_BUSMODE                  0x08
+#define SDMMC_BLKLEN                   0x0C
+#define SDMMC_BLKCNT                   0x0E
+#define SDMMC_RSP                      0x10
+#define SDMMC_CBCR                     0x20
+#define SDMMC_INTMASK0                 0x24
+#define SDMMC_INTMASK1                 0x25
+#define SDMMC_STS0                     0x28
+#define SDMMC_STS1                     0x29
+#define SDMMC_STS2                     0x2A
+#define SDMMC_STS3                     0x2B
+#define SDMMC_RSPTIMEOUT               0x2C
+#define SDMMC_CLK                      0x30    /* VT8500 only */
+#define SDMMC_EXTCTRL                  0x34
+#define SDMMC_SBLKLEN                  0x38
+#define SDMMC_DMATIMEOUT               0x3C
+
+
+/* SDMMC_CTLR bit fields */
+#define CTLR_CMD_START                 0x01
+#define CTLR_CMD_WRITE                 0x04
+#define CTLR_FIFO_RESET                        0x08
+
+/* SDMMC_BUSMODE bit fields */
+#define BM_SPI_MODE                    0x01
+#define BM_FOURBIT_MODE                        0x02
+#define BM_EIGHTBIT_MODE               0x04
+#define BM_SD_OFF                      0x10
+#define BM_SPI_CS                      0x20
+#define BM_SD_POWER                    0x40
+#define BM_SOFT_RESET                  0x80
+#define BM_ONEBIT_MASK                 0xFD
+
+/* SDMMC_BLKLEN bit fields */
+#define BLKL_CRCERR_ABORT              0x0800
+#define BLKL_CD_POL_HIGH               0x1000
+#define BLKL_GPI_CD                    0x2000
+#define BLKL_DATA3_CD                  0x4000
+#define BLKL_INT_ENABLE                        0x8000
+
+/* SDMMC_INTMASK0 bit fields */
+#define INT0_MBLK_TRAN_DONE_INT_EN     0x10
+#define INT0_BLK_TRAN_DONE_INT_EN      0x20
+#define INT0_CD_INT_EN                 0x40
+#define INT0_DI_INT_EN                 0x80
+
+/* SDMMC_INTMASK1 bit fields */
+#define INT1_CMD_RES_TRAN_DONE_INT_EN  0x02
+#define INT1_CMD_RES_TOUT_INT_EN       0x04
+#define INT1_MBLK_AUTO_STOP_INT_EN     0x08
+#define INT1_DATA_TOUT_INT_EN          0x10
+#define INT1_RESCRC_ERR_INT_EN         0x20
+#define INT1_RCRC_ERR_INT_EN           0x40
+#define INT1_WCRC_ERR_INT_EN           0x80
+
+/* SDMMC_STS0 bit fields */
+#define STS0_WRITE_PROTECT             0x02
+#define STS0_CD_DATA3                  0x04
+#define STS0_CD_GPI                    0x08
+#define STS0_MBLK_DONE                 0x10
+#define STS0_BLK_DONE                  0x20
+#define STS0_CARD_DETECT               0x40
+#define STS0_DEVICE_INS                        0x80
+
+/* SDMMC_STS1 bit fields */
+#define STS1_SDIO_INT                  0x01
+#define STS1_CMDRSP_DONE               0x02
+#define STS1_RSP_TIMEOUT               0x04
+#define STS1_AUTOSTOP_DONE             0x08
+#define STS1_DATA_TIMEOUT              0x10
+#define STS1_RSP_CRC_ERR               0x20
+#define STS1_RCRC_ERR                  0x40
+#define STS1_WCRC_ERR                  0x80
+
+/* SDMMC_STS2 bit fields */
+#define STS2_CMD_RES_BUSY              0x10
+#define STS2_DATARSP_BUSY              0x20
+#define STS2_DIS_FORCECLK              0x80
+
+
+/* MMC/SD DMA Controller Registers */
+#define SDDMA_GCR                      0x100
+#define SDDMA_IER                      0x104
+#define SDDMA_ISR                      0x108
+#define SDDMA_DESPR                    0x10C
+#define SDDMA_RBR                      0x110
+#define SDDMA_DAR                      0x114
+#define SDDMA_BAR                      0x118
+#define SDDMA_CPR                      0x11C
+#define SDDMA_CCR                      0x120
+
+
+/* SDDMA_GCR bit fields */
+#define DMA_GCR_DMA_EN                 0x00000001
+#define DMA_GCR_SOFT_RESET             0x00000100
+
+/* SDDMA_IER bit fields */
+#define DMA_IER_INT_EN                 0x00000001
+
+/* SDDMA_ISR bit fields */
+#define DMA_ISR_INT_STS                        0x00000001
+
+/* SDDMA_RBR bit fields */
+#define DMA_RBR_FORMAT                 0x40000000
+#define DMA_RBR_END                    0x80000000
+
+/* SDDMA_CCR bit fields */
+#define DMA_CCR_RUN                    0x00000080
+#define DMA_CCR_IF_TO_PERIPHERAL       0x00000000
+#define DMA_CCR_PERIPHERAL_TO_IF       0x00400000
+
+/* SDDMA_CCR event status */
+#define DMA_CCR_EVT_NO_STATUS          0x00000000
+#define DMA_CCR_EVT_UNDERRUN           0x00000001
+#define DMA_CCR_EVT_OVERRUN            0x00000002
+#define DMA_CCR_EVT_DESP_READ          0x00000003
+#define DMA_CCR_EVT_DATA_RW            0x00000004
+#define DMA_CCR_EVT_EARLY_END          0x00000005
+#define DMA_CCR_EVT_SUCCESS            0x0000000F
+
+#define PDMA_READ                      0x00
+#define PDMA_WRITE                     0x01
+
+#define WMT_SD_POWER_OFF               0
+#define WMT_SD_POWER_ON                        1
+
+struct wmt_dma_descriptor {
+       u32 flags;
+       u32 data_buffer_addr;
+       u32 branch_addr;
+       u32 reserved1;
+};
+
+struct wmt_mci_caps {
+       unsigned int    f_min;
+       unsigned int    f_max;
+       u32             ocr_avail;
+       u32             caps;
+       u32             max_seg_size;
+       u32             max_segs;
+       u32             max_blk_size;
+};
+
+struct wmt_mci_priv {
+       struct mmc_host *mmc;
+       void __iomem *sdmmc_base;
+
+       int irq_regular;
+       int irq_dma;
+
+       void *dma_desc_buffer;
+       dma_addr_t dma_desc_device_addr;
+
+       struct completion cmdcomp;
+       struct completion datacomp;
+
+       struct completion *comp_cmd;
+       struct completion *comp_dma;
+
+       struct mmc_request *req;
+       struct mmc_command *cmd;
+
+       struct clk *clk_sdmmc;
+       struct device *dev;
+
+       u8 power_inverted;
+       u8 cd_inverted;
+};
+
+static void wmt_set_sd_power(struct wmt_mci_priv *priv, int enable)
+{
+       u32 reg_tmp;
+       if (enable) {
+               if (priv->power_inverted) {
+                       reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+                       writeb(reg_tmp | BM_SD_OFF,
+                              priv->sdmmc_base + SDMMC_BUSMODE);
+               } else {
+                       reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+                       writeb(reg_tmp & (~BM_SD_OFF),
+                              priv->sdmmc_base + SDMMC_BUSMODE);
+               }
+       } else {
+               if (priv->power_inverted) {
+                       reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+                       writeb(reg_tmp & (~BM_SD_OFF),
+                              priv->sdmmc_base + SDMMC_BUSMODE);
+               } else {
+                       reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+                       writeb(reg_tmp | BM_SD_OFF,
+                              priv->sdmmc_base + SDMMC_BUSMODE);
+               }
+       }
+}
+
+static void wmt_mci_read_response(struct mmc_host *mmc)
+{
+       struct wmt_mci_priv *priv;
+       int idx1, idx2;
+       u8 tmp_resp;
+       u32 response;
+
+       priv = mmc_priv(mmc);
+
+       for (idx1 = 0; idx1 < 4; idx1++) {
+               response = 0;
+               for (idx2 = 0; idx2 < 4; idx2++) {
+                       if ((idx1 == 3) && (idx2 == 3))
+                               tmp_resp = readb(priv->sdmmc_base + SDMMC_RSP);
+                       else
+                               tmp_resp = readb(priv->sdmmc_base + SDMMC_RSP +
+                                                (idx1*4) + idx2 + 1);
+                       response |= (tmp_resp << (idx2 * 8));
+               }
+               priv->cmd->resp[idx1] = cpu_to_be32(response);
+       }
+}
+
+static void wmt_mci_start_command(struct wmt_mci_priv *priv)
+{
+       u32 reg_tmp;
+
+       reg_tmp = readb(priv->sdmmc_base + SDMMC_CTLR);
+       writeb(reg_tmp | CTLR_CMD_START, priv->sdmmc_base + SDMMC_CTLR);
+}
+
+static int wmt_mci_send_command(struct mmc_host *mmc, u8 command, u8 cmdtype,
+                               u32 arg, u8 rsptype)
+{
+       struct wmt_mci_priv *priv;
+       u32 reg_tmp;
+
+       priv = mmc_priv(mmc);
+
+       /* write command, arg, resptype registers */
+       writeb(command, priv->sdmmc_base + SDMMC_CMD);
+       writel(arg, priv->sdmmc_base + SDMMC_ARG);
+       writeb(rsptype, priv->sdmmc_base + SDMMC_RSPTYPE);
+
+       /* reset response FIFO */
+       reg_tmp = readb(priv->sdmmc_base + SDMMC_CTLR);
+       writeb(reg_tmp | CTLR_FIFO_RESET, priv->sdmmc_base + SDMMC_CTLR);
+
+       /* ensure clock enabled - VT3465 */
+       wmt_set_sd_power(priv, WMT_SD_POWER_ON);
+
+       /* clear status bits */
+       writeb(0xFF, priv->sdmmc_base + SDMMC_STS0);
+       writeb(0xFF, priv->sdmmc_base + SDMMC_STS1);
+       writeb(0xFF, priv->sdmmc_base + SDMMC_STS2);
+       writeb(0xFF, priv->sdmmc_base + SDMMC_STS3);
+
+       /* set command type */
+       reg_tmp = readb(priv->sdmmc_base + SDMMC_CTLR);
+       writeb((reg_tmp & 0x0F) | (cmdtype << 4),
+              priv->sdmmc_base + SDMMC_CTLR);
+
+       return 0;
+}
+
+static void wmt_mci_disable_dma(struct wmt_mci_priv *priv)
+{
+       writel(DMA_ISR_INT_STS, priv->sdmmc_base + SDDMA_ISR);
+       writel(0, priv->sdmmc_base + SDDMA_IER);
+}
+
+static void wmt_complete_data_request(struct wmt_mci_priv *priv)
+{
+       struct mmc_request *req;
+       req = priv->req;
+
+       req->data->bytes_xfered = req->data->blksz * req->data->blocks;
+
+       /* unmap the DMA pages used for write data */
+       if (req->data->flags & MMC_DATA_WRITE)
+               dma_unmap_sg(mmc_dev(priv->mmc), req->data->sg,
+                            req->data->sg_len, DMA_TO_DEVICE);
+       else
+               dma_unmap_sg(mmc_dev(priv->mmc), req->data->sg,
+                            req->data->sg_len, DMA_FROM_DEVICE);
+
+       /* Check if the DMA ISR returned a data error */
+       if ((req->cmd->error) || (req->data->error))
+               mmc_request_done(priv->mmc, req);
+       else {
+               wmt_mci_read_response(priv->mmc);
+               if (!req->data->stop) {
+                       /* single-block read/write requests end here */
+                       mmc_request_done(priv->mmc, req);
+               } else {
+                       /*
+                        * we change the priv->cmd variable so the response is
+                        * stored in the stop struct rather than the original
+                        * calling command struct
+                        */
+                       priv->comp_cmd = &priv->cmdcomp;
+                       init_completion(priv->comp_cmd);
+                       priv->cmd = req->data->stop;
+                       wmt_mci_send_command(priv->mmc, req->data->stop->opcode,
+                                            7, req->data->stop->arg, 9);
+                       wmt_mci_start_command(priv);
+               }
+       }
+}
+
+static irqreturn_t wmt_mci_dma_isr(int irq_num, void *data)
+{
+       struct mmc_host *mmc;
+       struct wmt_mci_priv *priv;
+
+       int status;
+
+       priv = (struct wmt_mci_priv *)data;
+       mmc = priv->mmc;
+
+       status = readl(priv->sdmmc_base + SDDMA_CCR) & 0x0F;
+
+       if (status != DMA_CCR_EVT_SUCCESS) {
+               dev_err(priv->dev, "DMA Error: Status = %d\n", status);
+               priv->req->data->error = -ETIMEDOUT;
+               complete(priv->comp_dma);
+               return IRQ_HANDLED;
+       }
+
+       priv->req->data->error = 0;
+
+       wmt_mci_disable_dma(priv);
+
+       complete(priv->comp_dma);
+
+       if (priv->comp_cmd) {
+               if (completion_done(priv->comp_cmd)) {
+                       /*
+                        * if the command (regular) interrupt has already
+                        * completed, finish off the request otherwise we wait
+                        * for the command interrupt and finish from there.
+                        */
+                       wmt_complete_data_request(priv);
+               }
+       }
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t wmt_mci_regular_isr(int irq_num, void *data)
+{
+       struct wmt_mci_priv *priv;
+       u32 status0;
+       u32 status1;
+       u32 status2;
+       u32 reg_tmp;
+       int cmd_done;
+
+       priv = (struct wmt_mci_priv *)data;
+       cmd_done = 0;
+       status0 = readb(priv->sdmmc_base + SDMMC_STS0);
+       status1 = readb(priv->sdmmc_base + SDMMC_STS1);
+       status2 = readb(priv->sdmmc_base + SDMMC_STS2);
+
+       /* Check for card insertion */
+       reg_tmp = readb(priv->sdmmc_base + SDMMC_INTMASK0);
+       if ((reg_tmp & INT0_DI_INT_EN) && (status0 & STS0_DEVICE_INS)) {
+               mmc_detect_change(priv->mmc, 0);
+               if (priv->cmd)
+                       priv->cmd->error = -ETIMEDOUT;
+               if (priv->comp_cmd)
+                       complete(priv->comp_cmd);
+               if (priv->comp_dma) {
+                       wmt_mci_disable_dma(priv);
+                       complete(priv->comp_dma);
+               }
+               writeb(STS0_DEVICE_INS, priv->sdmmc_base + SDMMC_STS0);
+               return IRQ_HANDLED;
+       }
+
+       if ((!priv->req->data) ||
+           ((priv->req->data->stop) && (priv->cmd == priv->req->data->stop))) {
+               /* handle non-data & stop_transmission requests */
+               if (status1 & STS1_CMDRSP_DONE) {
+                       priv->cmd->error = 0;
+                       cmd_done = 1;
+               } else if ((status1 & STS1_RSP_TIMEOUT) ||
+                          (status1 & STS1_DATA_TIMEOUT)) {
+                       priv->cmd->error = -ETIMEDOUT;
+                       cmd_done = 1;
+               }
+
+               if (cmd_done) {
+                       priv->comp_cmd = NULL;
+
+                       if (!priv->cmd->error)
+                               wmt_mci_read_response(priv->mmc);
+
+                       priv->cmd = NULL;
+
+                       mmc_request_done(priv->mmc, priv->req);
+               }
+       } else {
+               /* handle data requests */
+               if (status1 & STS1_CMDRSP_DONE) {
+                       if (priv->cmd)
+                               priv->cmd->error = 0;
+                       if (priv->comp_cmd)
+                               complete(priv->comp_cmd);
+               }
+
+               if ((status1 & STS1_RSP_TIMEOUT) ||
+                   (status1 & STS1_DATA_TIMEOUT)) {
+                       if (priv->cmd)
+                               priv->cmd->error = -ETIMEDOUT;
+                       if (priv->comp_cmd)
+                               complete(priv->comp_cmd);
+                       if (priv->comp_dma) {
+                               wmt_mci_disable_dma(priv);
+                               complete(priv->comp_dma);
+                       }
+               }
+
+               if (priv->comp_dma) {
+                       /*
+                        * If the dma interrupt has already completed, finish
+                        * off the request; otherwise we wait for the DMA
+                        * interrupt and finish from there.
+                        */
+                       if (completion_done(priv->comp_dma))
+                               wmt_complete_data_request(priv);
+               }
+       }
+
+       writeb(status0, priv->sdmmc_base + SDMMC_STS0);
+       writeb(status1, priv->sdmmc_base + SDMMC_STS1);
+       writeb(status2, priv->sdmmc_base + SDMMC_STS2);
+
+       return IRQ_HANDLED;
+}
+
+static void wmt_reset_hardware(struct mmc_host *mmc)
+{
+       struct wmt_mci_priv *priv;
+       u32 reg_tmp;
+
+       priv = mmc_priv(mmc);
+
+       /* reset controller */
+       reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+       writeb(reg_tmp | BM_SOFT_RESET, priv->sdmmc_base + SDMMC_BUSMODE);
+
+       /* reset response FIFO */
+       reg_tmp = readb(priv->sdmmc_base + SDMMC_CTLR);
+       writeb(reg_tmp | CTLR_FIFO_RESET, priv->sdmmc_base + SDMMC_CTLR);
+
+       /* enable GPI pin to detect card */
+       writew(BLKL_INT_ENABLE | BLKL_GPI_CD, priv->sdmmc_base + SDMMC_BLKLEN);
+
+       /* clear interrupt status */
+       writeb(0xFF, priv->sdmmc_base + SDMMC_STS0);
+       writeb(0xFF, priv->sdmmc_base + SDMMC_STS1);
+
+       /* setup interrupts */
+       writeb(INT0_CD_INT_EN | INT0_DI_INT_EN, priv->sdmmc_base +
+              SDMMC_INTMASK0);
+       writeb(INT1_DATA_TOUT_INT_EN | INT1_CMD_RES_TRAN_DONE_INT_EN |
+              INT1_CMD_RES_TOUT_INT_EN, priv->sdmmc_base + SDMMC_INTMASK1);
+
+       /* set the DMA timeout */
+       writew(8191, priv->sdmmc_base + SDMMC_DMATIMEOUT);
+
+       /* auto clock freezing enable */
+       reg_tmp = readb(priv->sdmmc_base + SDMMC_STS2);
+       writeb(reg_tmp | STS2_DIS_FORCECLK, priv->sdmmc_base + SDMMC_STS2);
+
+       /* set a default clock speed of 400Khz */
+       clk_set_rate(priv->clk_sdmmc, 400000);
+}
+
+static int wmt_dma_init(struct mmc_host *mmc)
+{
+       struct wmt_mci_priv *priv;
+
+       priv = mmc_priv(mmc);
+
+       writel(DMA_GCR_SOFT_RESET, priv->sdmmc_base + SDDMA_GCR);
+       writel(DMA_GCR_DMA_EN, priv->sdmmc_base + SDDMA_GCR);
+       if ((readl(priv->sdmmc_base + SDDMA_GCR) & DMA_GCR_DMA_EN) != 0)
+               return 0;
+       else
+               return 1;
+}
+
+static void wmt_dma_init_descriptor(struct wmt_dma_descriptor *desc,
+               u16 req_count, u32 buffer_addr, u32 branch_addr, int end)
+{
+       desc->flags = 0x40000000 | req_count;
+       if (end)
+               desc->flags |= 0x80000000;
+       desc->data_buffer_addr = buffer_addr;
+       desc->branch_addr = branch_addr;
+}
+
+static void wmt_dma_config(struct mmc_host *mmc, u32 descaddr, u8 dir)
+{
+       struct wmt_mci_priv *priv;
+       u32 reg_tmp;
+
+       priv = mmc_priv(mmc);
+
+       /* Enable DMA Interrupts */
+       writel(DMA_IER_INT_EN, priv->sdmmc_base + SDDMA_IER);
+
+       /* Write DMA Descriptor Pointer Register */
+       writel(descaddr, priv->sdmmc_base + SDDMA_DESPR);
+
+       writel(0x00, priv->sdmmc_base + SDDMA_CCR);
+
+       if (dir == PDMA_WRITE) {
+               reg_tmp = readl(priv->sdmmc_base + SDDMA_CCR);
+               writel(reg_tmp & DMA_CCR_IF_TO_PERIPHERAL, priv->sdmmc_base +
+                      SDDMA_CCR);
+       } else {
+               reg_tmp = readl(priv->sdmmc_base + SDDMA_CCR);
+               writel(reg_tmp | DMA_CCR_PERIPHERAL_TO_IF, priv->sdmmc_base +
+                      SDDMA_CCR);
+       }
+}
+
+static void wmt_dma_start(struct wmt_mci_priv *priv)
+{
+       u32 reg_tmp;
+
+       reg_tmp = readl(priv->sdmmc_base + SDDMA_CCR);
+       writel(reg_tmp | DMA_CCR_RUN, priv->sdmmc_base + SDDMA_CCR);
+}
+
+static void wmt_mci_request(struct mmc_host *mmc, struct mmc_request *req)
+{
+       struct wmt_mci_priv *priv;
+       struct wmt_dma_descriptor *desc;
+       u8 command;
+       u8 cmdtype;
+       u32 arg;
+       u8 rsptype;
+       u32 reg_tmp;
+
+       struct scatterlist *sg;
+       int i;
+       int sg_cnt;
+       int offset;
+       u32 dma_address;
+       int desc_cnt;
+
+       priv = mmc_priv(mmc);
+       priv->req = req;
+
+       /*
+        * Use the cmd variable to pass a pointer to the resp[] structure
+        * This is required on multi-block requests to pass the pointer to the
+        * stop command
+        */
+       priv->cmd = req->cmd;
+
+       command = req->cmd->opcode;
+       arg = req->cmd->arg;
+       rsptype = mmc_resp_type(req->cmd);
+       cmdtype = 0;
+
+       /* rsptype=7 only valid for SPI commands - should be =2 for SD */
+       if (rsptype == 7)
+               rsptype = 2;
+       /* rsptype=21 is R1B, convert for controller */
+       if (rsptype == 21)
+               rsptype = 9;
+
+       if (!req->data) {
+               wmt_mci_send_command(mmc, command, cmdtype, arg, rsptype);
+               wmt_mci_start_command(priv);
+               /* completion is now handled in the regular_isr() */
+       }
+       if (req->data) {
+               priv->comp_cmd = &priv->cmdcomp;
+               init_completion(priv->comp_cmd);
+
+               wmt_dma_init(mmc);
+
+               /* set controller data length */
+               reg_tmp = readw(priv->sdmmc_base + SDMMC_BLKLEN);
+               writew((reg_tmp & 0xF800) | (req->data->blksz - 1),
+                      priv->sdmmc_base + SDMMC_BLKLEN);
+
+               /* set controller block count */
+               writew(req->data->blocks, priv->sdmmc_base + SDMMC_BLKCNT);
+
+               desc = (struct wmt_dma_descriptor *)priv->dma_desc_buffer;
+
+               if (req->data->flags & MMC_DATA_WRITE) {
+                       sg_cnt = dma_map_sg(mmc_dev(mmc), req->data->sg,
+                                           req->data->sg_len, DMA_TO_DEVICE);
+                       cmdtype = 1;
+                       if (req->data->blocks > 1)
+                               cmdtype = 3;
+               } else {
+                       sg_cnt = dma_map_sg(mmc_dev(mmc), req->data->sg,
+                                           req->data->sg_len, DMA_FROM_DEVICE);
+                       cmdtype = 2;
+                       if (req->data->blocks > 1)
+                               cmdtype = 4;
+               }
+
+               dma_address = priv->dma_desc_device_addr + 16;
+               desc_cnt = 0;
+
+               for_each_sg(req->data->sg, sg, sg_cnt, i) {
+                       offset = 0;
+                       while (offset < sg_dma_len(sg)) {
+                               wmt_dma_init_descriptor(desc, req->data->blksz,
+                                               sg_dma_address(sg)+offset,
+                                               dma_address, 0);
+                               desc++;
+                               desc_cnt++;
+                               offset += req->data->blksz;
+                               dma_address += 16;
+                               if (desc_cnt == req->data->blocks)
+                                       break;
+                       }
+               }
+               desc--;
+               desc->flags |= 0x80000000;
+
+               if (req->data->flags & MMC_DATA_WRITE)
+                       wmt_dma_config(mmc, priv->dma_desc_device_addr,
+                                      PDMA_WRITE);
+               else
+                       wmt_dma_config(mmc, priv->dma_desc_device_addr,
+                                      PDMA_READ);
+
+               wmt_mci_send_command(mmc, command, cmdtype, arg, rsptype);
+
+               priv->comp_dma = &priv->datacomp;
+               init_completion(priv->comp_dma);
+
+               wmt_dma_start(priv);
+               wmt_mci_start_command(priv);
+       }
+}
+
+static void wmt_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+       struct wmt_mci_priv *priv;
+       u32 reg_tmp;
+
+       priv = mmc_priv(mmc);
+
+       if (ios->power_mode == MMC_POWER_UP) {
+               wmt_reset_hardware(mmc);
+
+               wmt_set_sd_power(priv, WMT_SD_POWER_ON);
+       }
+       if (ios->power_mode == MMC_POWER_OFF)
+               wmt_set_sd_power(priv, WMT_SD_POWER_OFF);
+
+       if (ios->clock != 0)
+               clk_set_rate(priv->clk_sdmmc, ios->clock);
+
+       switch (ios->bus_width) {
+       case MMC_BUS_WIDTH_8:
+               reg_tmp = readb(priv->sdmmc_base + SDMMC_EXTCTRL);
+               writeb(reg_tmp | 0x04, priv->sdmmc_base + SDMMC_EXTCTRL);
+               break;
+       case MMC_BUS_WIDTH_4:
+               reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+               writeb(reg_tmp | BM_FOURBIT_MODE, priv->sdmmc_base +
+                      SDMMC_BUSMODE);
+
+               reg_tmp = readb(priv->sdmmc_base + SDMMC_EXTCTRL);
+               writeb(reg_tmp & 0xFB, priv->sdmmc_base + SDMMC_EXTCTRL);
+               break;
+       case MMC_BUS_WIDTH_1:
+               reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+               writeb(reg_tmp & BM_ONEBIT_MASK, priv->sdmmc_base +
+                      SDMMC_BUSMODE);
+
+               reg_tmp = readb(priv->sdmmc_base + SDMMC_EXTCTRL);
+               writeb(reg_tmp & 0xFB, priv->sdmmc_base + SDMMC_EXTCTRL);
+               break;
+       }
+}
+
+static int wmt_mci_get_ro(struct mmc_host *mmc)
+{
+       struct wmt_mci_priv *priv = mmc_priv(mmc);
+
+       return !(readb(priv->sdmmc_base + SDMMC_STS0) & STS0_WRITE_PROTECT);
+}
+
+static int wmt_mci_get_cd(struct mmc_host *mmc)
+{
+       struct wmt_mci_priv *priv = mmc_priv(mmc);
+       u32 cd = (readb(priv->sdmmc_base + SDMMC_STS0) & STS0_CD_GPI) >> 3;
+
+       return !(cd ^ priv->cd_inverted);
+}
+
+static struct mmc_host_ops wmt_mci_ops = {
+       .request = wmt_mci_request,
+       .set_ios = wmt_mci_set_ios,
+       .get_ro = wmt_mci_get_ro,
+       .get_cd = wmt_mci_get_cd,
+};
+
+/* Controller capabilities */
+static struct wmt_mci_caps wm8505_caps = {
+       .f_min = 390425,
+       .f_max = 50000000,
+       .ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34,
+       .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MMC_HIGHSPEED |
+               MMC_CAP_SD_HIGHSPEED,
+       .max_seg_size = 65024,
+       .max_segs = 128,
+       .max_blk_size = 2048,
+};
+
+static struct of_device_id wmt_mci_dt_ids[] = {
+       { .compatible = "wm,wm8505-sdhc", .data = &wm8505_caps },
+       { /* Sentinel */ },
+};
+
+static int __devinit wmt_mci_probe(struct platform_device *pdev)
+{
+       struct mmc_host *mmc;
+       struct wmt_mci_priv *priv;
+       struct device_node *np = pdev->dev.of_node;
+       const struct of_device_id *of_id =
+               of_match_device(wmt_mci_dt_ids, &pdev->dev);
+       const struct wmt_mci_caps *wmt_caps = of_id->data;
+       int ret;
+       int regular_irq, dma_irq;
+
+       if (!of_id || !of_id->data) {
+               dev_err(&pdev->dev, "Controller capabilities data missing\n");
+               return -EFAULT;
+       }
+
+       if (!np) {
+               dev_err(&pdev->dev, "Missing SDMMC description in devicetree\n");
+               return -EFAULT;
+       }
+
+       regular_irq = irq_of_parse_and_map(np, 0);
+       dma_irq = irq_of_parse_and_map(np, 1);
+
+       if (!regular_irq || !dma_irq) {
+               dev_err(&pdev->dev, "Getting IRQs failed!\n");
+               ret = -ENXIO;
+               goto fail1;
+       }
+
+       mmc = mmc_alloc_host(sizeof(struct wmt_mci_priv), &pdev->dev);
+       if (!mmc) {
+               dev_err(&pdev->dev, "Failed to allocate mmc_host\n");
+               ret = -ENOMEM;
+               goto fail1;
+       }
+
+       mmc->ops = &wmt_mci_ops;
+       mmc->f_min = wmt_caps->f_min;
+       mmc->f_max = wmt_caps->f_max;
+       mmc->ocr_avail = wmt_caps->ocr_avail;
+       mmc->caps = wmt_caps->caps;
+
+       mmc->max_seg_size = wmt_caps->max_seg_size;
+       mmc->max_segs = wmt_caps->max_segs;
+       mmc->max_blk_size = wmt_caps->max_blk_size;
+
+       mmc->max_req_size = (16*512*mmc->max_segs);
+       mmc->max_blk_count = mmc->max_req_size / 512;
+
+       priv = mmc_priv(mmc);
+       priv->mmc = mmc;
+       priv->dev = &pdev->dev;
+
+       priv->power_inverted = 0;
+       priv->cd_inverted = 0;
+
+       if (of_get_property(np, "sdon-inverted", NULL))
+               priv->power_inverted = 1;
+       if (of_get_property(np, "cd-inverted", NULL))
+               priv->cd_inverted = 1;
+
+       priv->sdmmc_base = of_iomap(np, 0);
+       if (!priv->sdmmc_base) {
+               dev_err(&pdev->dev, "Failed to map IO space\n");
+               ret = -ENOMEM;
+               goto fail2;
+       }
+
+       priv->irq_regular = regular_irq;
+       priv->irq_dma = dma_irq;
+
+       ret = request_irq(regular_irq, wmt_mci_regular_isr, 0, "sdmmc", priv);
+       if (ret) {
+               dev_err(&pdev->dev, "Register regular IRQ fail\n");
+               goto fail3;
+       }
+
+       ret = request_irq(dma_irq, wmt_mci_dma_isr, 32, "sdmmc", priv);
+       if (ret) {
+               dev_err(&pdev->dev, "Register DMA IRQ fail\n");
+               goto fail4;
+       }
+
+       /* alloc some DMA buffers for descriptors/transfers */
+       priv->dma_desc_buffer = dma_alloc_coherent(&pdev->dev,
+                                                  mmc->max_blk_count * 16,
+                                                  &priv->dma_desc_device_addr,
+                                                  208);
+       if (!priv->dma_desc_buffer) {
+               dev_err(&pdev->dev, "DMA alloc fail\n");
+               ret = -EPERM;
+               goto fail5;
+       }
+
+       platform_set_drvdata(pdev, mmc);
+
+       priv->clk_sdmmc = of_clk_get(np, 0);
+       if (IS_ERR(priv->clk_sdmmc)) {
+               dev_err(&pdev->dev, "Error getting clock\n");
+               ret = PTR_ERR(priv->clk_sdmmc);
+               goto fail5;
+       }
+
+       clk_prepare_enable(priv->clk_sdmmc);
+
+       /* configure the controller to a known 'ready' state */
+       wmt_reset_hardware(mmc);
+
+       mmc_add_host(mmc);
+
+       dev_info(&pdev->dev, "WMT SDHC Controller initialized\n");
+
+       return 0;
+fail5:
+       free_irq(dma_irq, priv);
+fail4:
+       free_irq(regular_irq, priv);
+fail3:
+       iounmap(priv->sdmmc_base);
+fail2:
+       mmc_free_host(mmc);
+fail1:
+       return ret;
+}
+
+static int __devexit wmt_mci_remove(struct platform_device *pdev)
+{
+       struct mmc_host *mmc;
+       struct wmt_mci_priv *priv;
+       struct resource *res;
+       u32 reg_tmp;
+
+       mmc = platform_get_drvdata(pdev);
+       priv = mmc_priv(mmc);
+
+       /* reset SD controller */
+       reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+       writel(reg_tmp | BM_SOFT_RESET, priv->sdmmc_base + SDMMC_BUSMODE);
+       reg_tmp = readw(priv->sdmmc_base + SDMMC_BLKLEN);
+       writew(reg_tmp & ~(0xA000), priv->sdmmc_base + SDMMC_BLKLEN);
+       writeb(0xFF, priv->sdmmc_base + SDMMC_STS0);
+       writeb(0xFF, priv->sdmmc_base + SDMMC_STS1);
+
+       /* release the dma buffers */
+       dma_free_coherent(&pdev->dev, priv->mmc->max_blk_count * 16,
+                         priv->dma_desc_buffer, priv->dma_desc_device_addr);
+
+       mmc_remove_host(mmc);
+
+       free_irq(priv->irq_regular, priv);
+       free_irq(priv->irq_dma, priv);
+
+       iounmap(priv->sdmmc_base);
+
+       clk_disable_unprepare(priv->clk_sdmmc);
+       clk_put(priv->clk_sdmmc);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(res->start, res->end - res->start + 1);
+
+       mmc_free_host(mmc);
+
+       platform_set_drvdata(pdev, NULL);
+
+       dev_info(&pdev->dev, "WMT MCI device removed\n");
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int wmt_mci_suspend(struct device *dev)
+{
+       u32 reg_tmp;
+       struct platform_device *pdev = to_platform_device(dev);
+       struct mmc_host *mmc = platform_get_drvdata(pdev);
+       struct wmt_mci_priv *priv;
+       int ret;
+
+       if (!mmc)
+               return 0;
+
+       priv = mmc_priv(mmc);
+       ret = mmc_suspend_host(mmc);
+
+       if (!ret) {
+               reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+               writeb(reg_tmp | BM_SOFT_RESET, priv->sdmmc_base +
+                      SDMMC_BUSMODE);
+
+               reg_tmp = readw(priv->sdmmc_base + SDMMC_BLKLEN);
+               writew(reg_tmp & 0x5FFF, priv->sdmmc_base + SDMMC_BLKLEN);
+
+               writeb(0xFF, priv->sdmmc_base + SDMMC_STS0);
+               writeb(0xFF, priv->sdmmc_base + SDMMC_STS1);
+
+               clk_disable(priv->clk_sdmmc);
+       }
+       return ret;
+}
+
+static int wmt_mci_resume(struct device *dev)
+{
+       u32 reg_tmp;
+       struct platform_device *pdev = to_platform_device(dev);
+       struct mmc_host *mmc = platform_get_drvdata(pdev);
+       struct wmt_mci_priv *priv;
+       int ret = 0;
+
+       if (mmc) {
+               priv = mmc_priv(mmc);
+               clk_enable(priv->clk_sdmmc);
+
+               reg_tmp = readb(priv->sdmmc_base + SDMMC_BUSMODE);
+               writeb(reg_tmp | BM_SOFT_RESET, priv->sdmmc_base +
+                      SDMMC_BUSMODE);
+
+               reg_tmp = readw(priv->sdmmc_base + SDMMC_BLKLEN);
+               writew(reg_tmp | (BLKL_GPI_CD | BLKL_INT_ENABLE),
+                      priv->sdmmc_base + SDMMC_BLKLEN);
+
+               reg_tmp = readb(priv->sdmmc_base + SDMMC_INTMASK0);
+               writeb(reg_tmp | INT0_DI_INT_EN, priv->sdmmc_base +
+                      SDMMC_INTMASK0);
+
+               ret = mmc_resume_host(mmc);
+       }
+
+       return ret;
+}
+
+static const struct dev_pm_ops wmt_mci_pm = {
+       .suspend        = wmt_mci_suspend,
+       .resume         = wmt_mci_resume,
+};
+
+#define wmt_mci_pm_ops (&wmt_mci_pm)
+
+#else  /* !CONFIG_PM */
+
+#define wmt_mci_pm_ops NULL
+
+#endif
+
+static struct platform_driver wmt_mci_driver = {
+       .probe = wmt_mci_probe,
+       .remove = __exit_p(wmt_mci_remove),
+       .driver = {
+               .name = DRIVER_NAME,
+               .owner = THIS_MODULE,
+               .pm = wmt_mci_pm_ops,
+               .of_match_table = wmt_mci_dt_ids,
+       },
+};
+
+module_platform_driver(wmt_mci_driver);
+
+MODULE_DESCRIPTION("Wondermedia MMC/SD Driver");
+MODULE_AUTHOR("Tony Prisk");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, wmt_mci_dt_ids);
index 8f52fc8..5a5cd2a 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 374c46d..ec794a7 100644 (file)
@@ -1077,7 +1077,8 @@ EXPORT_SYMBOL_GPL(mtd_writev);
  * until the request succeeds or until the allocation size falls below
  * the system page size. This attempts to make sure it does not adversely
  * impact system performance, so when allocating more than one page, we
- * ask the memory allocator to avoid re-trying.
+ * ask the memory allocator to avoid re-trying, swapping, writing back
+ * or performing I/O.
  *
  * Note, this function also makes sure that the allocated buffer is aligned to
  * the MTD device's min. I/O unit, i.e. the "mtd->writesize" value.
@@ -1091,7 +1092,8 @@ EXPORT_SYMBOL_GPL(mtd_writev);
  */
 void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size)
 {
-       gfp_t flags = __GFP_NOWARN | __GFP_WAIT | __GFP_NORETRY;
+       gfp_t flags = __GFP_NOWARN | __GFP_WAIT |
+                      __GFP_NORETRY | __GFP_NO_KSWAPD;
        size_t min_alloc = max_t(size_t, mtd->writesize, PAGE_SIZE);
        void *kbuf;
 
index 9144557..92623ac 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 ec6841d..1a03b7f 100644 (file)
@@ -2983,13 +2983,15 @@ 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 &&
+                       (chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
+                       id_data[5] != 0x00) {
                /* Calc pagesize */
                mtd->writesize = 2048 << (extid & 0x03);
                extid >>= 2;
index 4fbfe96..f48ac5d 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 64be8f0..d9127e2 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 7153e0d..b3f41f2 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 da7b449..2144f61 100644 (file)
@@ -498,7 +498,7 @@ out:
  * @ubi: UBI device description object
  *
  * This function returns a physical eraseblock in case of success and a
- * negative error code in case of failure. Might sleep.
+ * negative error code in case of failure.
  */
 static int __wl_get_peb(struct ubi_device *ubi)
 {
@@ -540,13 +540,6 @@ retry:
         * ubi_wl_get_peb() after removing e from the pool. */
        prot_queue_add(ubi, e);
 #endif
-       err = ubi_self_check_all_ff(ubi, e->pnum, ubi->vid_hdr_aloffset,
-                                   ubi->peb_size - ubi->vid_hdr_aloffset);
-       if (err) {
-               ubi_err("new PEB %d does not contain all 0xFF bytes", e->pnum);
-               return err;
-       }
-
        return e->pnum;
 }
 
@@ -679,17 +672,30 @@ static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi)
 #else
 static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi)
 {
-       return find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF);
+       struct ubi_wl_entry *e;
+
+       e = find_wl_entry(ubi, &ubi->free, WL_FREE_MAX_DIFF);
+       self_check_in_wl_tree(ubi, e, &ubi->free);
+       rb_erase(&e->u.rb, &ubi->free);
+
+       return e;
 }
 
 int ubi_wl_get_peb(struct ubi_device *ubi)
 {
-       int peb;
+       int peb, err;
 
        spin_lock(&ubi->wl_lock);
        peb = __wl_get_peb(ubi);
        spin_unlock(&ubi->wl_lock);
 
+       err = ubi_self_check_all_ff(ubi, peb, ubi->vid_hdr_aloffset,
+                                   ubi->peb_size - ubi->vid_hdr_aloffset);
+       if (err) {
+               ubi_err("new PEB %d does not contain all 0xFF bytes", peb);
+               return err;
+       }
+
        return peb;
 }
 #endif
index b721902..a7d4735 100644 (file)
@@ -1379,6 +1379,8 @@ static void bond_compute_features(struct bonding *bond)
        struct net_device *bond_dev = bond->dev;
        netdev_features_t vlan_features = BOND_VLAN_FEATURES;
        unsigned short max_hard_header_len = ETH_HLEN;
+       unsigned int gso_max_size = GSO_MAX_SIZE;
+       u16 gso_max_segs = GSO_MAX_SEGS;
        int i;
        unsigned int flags, dst_release_flag = IFF_XMIT_DST_RELEASE;
 
@@ -1394,11 +1396,16 @@ static void bond_compute_features(struct bonding *bond)
                dst_release_flag &= slave->dev->priv_flags;
                if (slave->dev->hard_header_len > max_hard_header_len)
                        max_hard_header_len = slave->dev->hard_header_len;
+
+               gso_max_size = min(gso_max_size, slave->dev->gso_max_size);
+               gso_max_segs = min(gso_max_segs, slave->dev->gso_max_segs);
        }
 
 done:
        bond_dev->vlan_features = vlan_features;
        bond_dev->hard_header_len = max_hard_header_len;
+       bond_dev->gso_max_segs = gso_max_segs;
+       netif_set_gso_max_size(bond_dev, gso_max_size);
 
        flags = bond_dev->priv_flags & ~IFF_XMIT_DST_RELEASE;
        bond_dev->priv_flags = flags | dst_release_flag;
@@ -1519,7 +1526,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
        /* no need to lock since we're protected by rtnl_lock */
        if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) {
                pr_debug("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
-               if (bond_vlan_used(bond)) {
+               if (vlan_uses_dev(bond_dev)) {
                        pr_err("%s: Error: cannot enslave VLAN challenged slave %s on VLAN enabled bond %s\n",
                               bond_dev->name, slave_dev->name, bond_dev->name);
                        return -EPERM;
@@ -3452,6 +3459,28 @@ static int bond_xmit_hash_policy_l34(struct sk_buff *skb, int count)
 
 /*-------------------------- Device entry points ----------------------------*/
 
+static void bond_work_init_all(struct bonding *bond)
+{
+       INIT_DELAYED_WORK(&bond->mcast_work,
+                         bond_resend_igmp_join_requests_delayed);
+       INIT_DELAYED_WORK(&bond->alb_work, bond_alb_monitor);
+       INIT_DELAYED_WORK(&bond->mii_work, bond_mii_monitor);
+       if (bond->params.mode == BOND_MODE_ACTIVEBACKUP)
+               INIT_DELAYED_WORK(&bond->arp_work, bond_activebackup_arp_mon);
+       else
+               INIT_DELAYED_WORK(&bond->arp_work, bond_loadbalance_arp_mon);
+       INIT_DELAYED_WORK(&bond->ad_work, bond_3ad_state_machine_handler);
+}
+
+static void bond_work_cancel_all(struct bonding *bond)
+{
+       cancel_delayed_work_sync(&bond->mii_work);
+       cancel_delayed_work_sync(&bond->arp_work);
+       cancel_delayed_work_sync(&bond->alb_work);
+       cancel_delayed_work_sync(&bond->ad_work);
+       cancel_delayed_work_sync(&bond->mcast_work);
+}
+
 static int bond_open(struct net_device *bond_dev)
 {
        struct bonding *bond = netdev_priv(bond_dev);
@@ -3474,41 +3503,27 @@ static int bond_open(struct net_device *bond_dev)
        }
        read_unlock(&bond->lock);
 
-       INIT_DELAYED_WORK(&bond->mcast_work, bond_resend_igmp_join_requests_delayed);
+       bond_work_init_all(bond);
 
        if (bond_is_lb(bond)) {
                /* bond_alb_initialize must be called before the timer
                 * is started.
                 */
-               if (bond_alb_initialize(bond, (bond->params.mode == BOND_MODE_ALB))) {
-                       /* something went wrong - fail the open operation */
+               if (bond_alb_initialize(bond, (bond->params.mode == BOND_MODE_ALB)))
                        return -ENOMEM;
-               }
-
-               INIT_DELAYED_WORK(&bond->alb_work, bond_alb_monitor);
                queue_delayed_work(bond->wq, &bond->alb_work, 0);
        }
 
-       if (bond->params.miimon) {  /* link check interval, in milliseconds. */
-               INIT_DELAYED_WORK(&bond->mii_work, bond_mii_monitor);
+       if (bond->params.miimon)  /* link check interval, in milliseconds. */
                queue_delayed_work(bond->wq, &bond->mii_work, 0);
-       }
 
        if (bond->params.arp_interval) {  /* arp interval, in milliseconds. */
-               if (bond->params.mode == BOND_MODE_ACTIVEBACKUP)
-                       INIT_DELAYED_WORK(&bond->arp_work,
-                                         bond_activebackup_arp_mon);
-               else
-                       INIT_DELAYED_WORK(&bond->arp_work,
-                                         bond_loadbalance_arp_mon);
-
                queue_delayed_work(bond->wq, &bond->arp_work, 0);
                if (bond->params.arp_validate)
                        bond->recv_probe = bond_arp_rcv;
        }
 
        if (bond->params.mode == BOND_MODE_8023AD) {
-               INIT_DELAYED_WORK(&bond->ad_work, bond_3ad_state_machine_handler);
                queue_delayed_work(bond->wq, &bond->ad_work, 0);
                /* register to receive LACPDUs */
                bond->recv_probe = bond_3ad_lacpdu_recv;
@@ -3523,34 +3538,10 @@ static int bond_close(struct net_device *bond_dev)
        struct bonding *bond = netdev_priv(bond_dev);
 
        write_lock_bh(&bond->lock);
-
        bond->send_peer_notif = 0;
-
        write_unlock_bh(&bond->lock);
 
-       if (bond->params.miimon) {  /* link check interval, in milliseconds. */
-               cancel_delayed_work_sync(&bond->mii_work);
-       }
-
-       if (bond->params.arp_interval) {  /* arp interval, in milliseconds. */
-               cancel_delayed_work_sync(&bond->arp_work);
-       }
-
-       switch (bond->params.mode) {
-       case BOND_MODE_8023AD:
-               cancel_delayed_work_sync(&bond->ad_work);
-               break;
-       case BOND_MODE_TLB:
-       case BOND_MODE_ALB:
-               cancel_delayed_work_sync(&bond->alb_work);
-               break;
-       default:
-               break;
-       }
-
-       if (delayed_work_pending(&bond->mcast_work))
-               cancel_delayed_work_sync(&bond->mcast_work);
-
+       bond_work_cancel_all(bond);
        if (bond_is_lb(bond)) {
                /* Must be called only after all
                 * slaves have been released
@@ -4429,26 +4420,6 @@ static void bond_setup(struct net_device *bond_dev)
        bond_dev->features |= bond_dev->hw_features;
 }
 
-static void bond_work_cancel_all(struct bonding *bond)
-{
-       if (bond->params.miimon && delayed_work_pending(&bond->mii_work))
-               cancel_delayed_work_sync(&bond->mii_work);
-
-       if (bond->params.arp_interval && delayed_work_pending(&bond->arp_work))
-               cancel_delayed_work_sync(&bond->arp_work);
-
-       if (bond->params.mode == BOND_MODE_ALB &&
-           delayed_work_pending(&bond->alb_work))
-               cancel_delayed_work_sync(&bond->alb_work);
-
-       if (bond->params.mode == BOND_MODE_8023AD &&
-           delayed_work_pending(&bond->ad_work))
-               cancel_delayed_work_sync(&bond->ad_work);
-
-       if (delayed_work_pending(&bond->mcast_work))
-               cancel_delayed_work_sync(&bond->mcast_work);
-}
-
 /*
 * Destroy a bonding device.
 * Must be under rtnl_lock when this function is called.
@@ -4699,12 +4670,13 @@ static int bond_check_params(struct bond_params *params)
             arp_ip_count++) {
                /* not complete check, but should be good enough to
                   catch mistakes */
-               if (!isdigit(arp_ip_target[arp_ip_count][0])) {
+               __be32 ip = in_aton(arp_ip_target[arp_ip_count]);
+               if (!isdigit(arp_ip_target[arp_ip_count][0]) ||
+                   ip == 0 || ip == htonl(INADDR_BROADCAST)) {
                        pr_warning("Warning: bad arp_ip_target module parameter (%s), ARP monitoring will not be performed\n",
                                   arp_ip_target[arp_ip_count]);
                        arp_interval = 0;
                } else {
-                       __be32 ip = in_aton(arp_ip_target[arp_ip_count]);
                        arp_target[arp_ip_count] = ip;
                }
        }
index dc15d24..1877ed7 100644 (file)
@@ -513,6 +513,8 @@ static ssize_t bonding_store_arp_interval(struct device *d,
        int new_value, ret = count;
        struct bonding *bond = to_bond(d);
 
+       if (!rtnl_trylock())
+               return restart_syscall();
        if (sscanf(buf, "%d", &new_value) != 1) {
                pr_err("%s: no arp_interval value specified.\n",
                       bond->dev->name);
@@ -539,10 +541,6 @@ static ssize_t bonding_store_arp_interval(struct device *d,
                pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n",
                        bond->dev->name, bond->dev->name);
                bond->params.miimon = 0;
-               if (delayed_work_pending(&bond->mii_work)) {
-                       cancel_delayed_work(&bond->mii_work);
-                       flush_workqueue(bond->wq);
-               }
        }
        if (!bond->params.arp_targets[0]) {
                pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n",
@@ -554,19 +552,12 @@ static ssize_t bonding_store_arp_interval(struct device *d,
                 * timer will get fired off when the open function
                 * is called.
                 */
-               if (!delayed_work_pending(&bond->arp_work)) {
-                       if (bond->params.mode == BOND_MODE_ACTIVEBACKUP)
-                               INIT_DELAYED_WORK(&bond->arp_work,
-                                                 bond_activebackup_arp_mon);
-                       else
-                               INIT_DELAYED_WORK(&bond->arp_work,
-                                                 bond_loadbalance_arp_mon);
-
-                       queue_delayed_work(bond->wq, &bond->arp_work, 0);
-               }
+               cancel_delayed_work_sync(&bond->mii_work);
+               queue_delayed_work(bond->wq, &bond->arp_work, 0);
        }
 
 out:
+       rtnl_unlock();
        return ret;
 }
 static DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR,
@@ -962,6 +953,8 @@ static ssize_t bonding_store_miimon(struct device *d,
        int new_value, ret = count;
        struct bonding *bond = to_bond(d);
 
+       if (!rtnl_trylock())
+               return restart_syscall();
        if (sscanf(buf, "%d", &new_value) != 1) {
                pr_err("%s: no miimon value specified.\n",
                       bond->dev->name);
@@ -993,10 +986,6 @@ static ssize_t bonding_store_miimon(struct device *d,
                                bond->params.arp_validate =
                                        BOND_ARP_VALIDATE_NONE;
                        }
-                       if (delayed_work_pending(&bond->arp_work)) {
-                               cancel_delayed_work(&bond->arp_work);
-                               flush_workqueue(bond->wq);
-                       }
                }
 
                if (bond->dev->flags & IFF_UP) {
@@ -1005,15 +994,12 @@ static ssize_t bonding_store_miimon(struct device *d,
                         * timer will get fired off when the open function
                         * is called.
                         */
-                       if (!delayed_work_pending(&bond->mii_work)) {
-                               INIT_DELAYED_WORK(&bond->mii_work,
-                                                 bond_mii_monitor);
-                               queue_delayed_work(bond->wq,
-                                                  &bond->mii_work, 0);
-                       }
+                       cancel_delayed_work_sync(&bond->arp_work);
+                       queue_delayed_work(bond->wq, &bond->mii_work, 0);
                }
        }
 out:
+       rtnl_unlock();
        return ret;
 }
 static DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR,
@@ -1060,7 +1046,7 @@ static ssize_t bonding_store_primary(struct device *d,
                goto out;
        }
 
-       sscanf(buf, "%16s", ifname); /* IFNAMSIZ */
+       sscanf(buf, "%15s", ifname); /* IFNAMSIZ */
 
        /* check to see if we are clearing primary */
        if (!strlen(ifname) || buf[0] == '\n') {
@@ -1237,7 +1223,7 @@ static ssize_t bonding_store_active_slave(struct device *d,
                goto out;
        }
 
-       sscanf(buf, "%16s", ifname); /* IFNAMSIZ */
+       sscanf(buf, "%15s", ifname); /* IFNAMSIZ */
 
        /* check to see if we are clearing active */
        if (!strlen(ifname) || buf[0] == '\n') {
@@ -1582,6 +1568,7 @@ static ssize_t bonding_store_slaves_active(struct device *d,
                goto out;
        }
 
+       read_lock(&bond->lock);
        bond_for_each_slave(bond, slave, i) {
                if (!bond_is_active_slave(slave)) {
                        if (new_value)
@@ -1590,6 +1577,7 @@ static ssize_t bonding_store_slaves_active(struct device *d,
                                slave->inactive = 1;
                }
        }
+       read_unlock(&bond->lock);
 out:
        return ret;
 }
index c78ecfc..a412bf6 100644 (file)
 
 #define FLEXCAN_MB_CODE_MASK           (0xf0ffffff)
 
-/* FLEXCAN hardware feature flags */
+/*
+ * FLEXCAN hardware feature flags
+ *
+ * Below is some version info we got:
+ *    SOC   Version   IP-Version  Glitch-  [TR]WRN_INT
+ *                                Filter?   connected?
+ *   MX25  FlexCAN2  03.00.00.00     no         no
+ *   MX28  FlexCAN2  03.00.04.00    yes        yes
+ *   MX35  FlexCAN2  03.00.00.00     no         no
+ *   MX53  FlexCAN2  03.00.00.00    yes         no
+ *   MX6s  FlexCAN3  10.00.12.00    yes        yes
+ *
+ * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected.
+ */
 #define FLEXCAN_HAS_V10_FEATURES       BIT(1) /* For core version >= 10 */
-#define FLEXCAN_HAS_BROKEN_ERR_STATE   BIT(2) /* Broken error state handling */
+#define FLEXCAN_HAS_BROKEN_ERR_STATE   BIT(2) /* [TR]WRN_INT not connected */
 
 /* Structure of the message buffer */
 struct flexcan_mb {
@@ -205,7 +218,7 @@ static struct flexcan_devtype_data fsl_p1010_devtype_data = {
 };
 static struct flexcan_devtype_data fsl_imx28_devtype_data;
 static struct flexcan_devtype_data fsl_imx6q_devtype_data = {
-       .features = FLEXCAN_HAS_V10_FEATURES | FLEXCAN_HAS_BROKEN_ERR_STATE,
+       .features = FLEXCAN_HAS_V10_FEATURES,
 };
 
 static const struct can_bittiming_const flexcan_bittiming_const = {
index f5b82ae..6525dbc 100644 (file)
 
 #include "sja1000.h"
 
-MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
+MODULE_AUTHOR("Stephane Grosjean <s.grosjean@peak-system.com>");
 MODULE_DESCRIPTION("Socket-CAN driver for PEAK PCAN PCI family cards");
 MODULE_SUPPORTED_DEVICE("PEAK PCAN PCI/PCIe/PCIeC miniPCI CAN cards");
+MODULE_SUPPORTED_DEVICE("PEAK PCAN miniPCIe/cPCI PC/104+ PCI/104e CAN Cards");
 MODULE_LICENSE("GPL v2");
 
 #define DRV_NAME  "peak_pci"
@@ -64,7 +65,11 @@ struct peak_pci_chan {
 #define PEAK_PCI_DEVICE_ID     0x0001  /* for PCI/PCIe slot cards */
 #define PEAK_PCIEC_DEVICE_ID   0x0002  /* for ExpressCard slot cards */
 #define PEAK_PCIE_DEVICE_ID    0x0003  /* for nextgen PCIe slot cards */
-#define PEAK_MPCI_DEVICE_ID    0x0008  /* The miniPCI slot cards */
+#define PEAK_CPCI_DEVICE_ID    0x0004  /* for nextgen cPCI slot cards */
+#define PEAK_MPCI_DEVICE_ID    0x0005  /* for nextgen miniPCI slot cards */
+#define PEAK_PC_104P_DEVICE_ID 0x0006  /* PCAN-PC/104+ cards */
+#define PEAK_PCI_104E_DEVICE_ID        0x0007  /* PCAN-PCI/104 Express cards */
+#define PEAK_MPCIE_DEVICE_ID   0x0008  /* The miniPCIe slot cards */
 
 #define PEAK_PCI_CHAN_MAX      4
 
@@ -76,6 +81,10 @@ static DEFINE_PCI_DEVICE_TABLE(peak_pci_tbl) = {
        {PEAK_PCI_VENDOR_ID, PEAK_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
        {PEAK_PCI_VENDOR_ID, PEAK_PCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
        {PEAK_PCI_VENDOR_ID, PEAK_MPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+       {PEAK_PCI_VENDOR_ID, PEAK_MPCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+       {PEAK_PCI_VENDOR_ID, PEAK_PC_104P_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+       {PEAK_PCI_VENDOR_ID, PEAK_PCI_104E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+       {PEAK_PCI_VENDOR_ID, PEAK_CPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
 #ifdef CONFIG_CAN_PEAK_PCIEC
        {PEAK_PCI_VENDOR_ID, PEAK_PCIEC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
 #endif
index 86f26a1..25723d8 100644 (file)
@@ -519,8 +519,10 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n,
        mc->pdev->dev.can.state = new_state;
 
        if (status_len & PCAN_USB_STATUSLEN_TIMESTAMP) {
+               struct skb_shared_hwtstamps *hwts = skb_hwtstamps(skb);
+
                peak_usb_get_ts_tv(&mc->pdev->time_ref, mc->ts16, &tv);
-               skb->tstamp = timeval_to_ktime(tv);
+               hwts->hwtstamp = timeval_to_ktime(tv);
        }
 
        netif_rx(skb);
@@ -605,6 +607,7 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len)
        struct sk_buff *skb;
        struct can_frame *cf;
        struct timeval tv;
+       struct skb_shared_hwtstamps *hwts;
 
        skb = alloc_can_skb(mc->netdev, &cf);
        if (!skb)
@@ -652,7 +655,8 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len)
 
        /* convert timestamp into kernel time */
        peak_usb_get_ts_tv(&mc->pdev->time_ref, mc->ts16, &tv);
-       skb->tstamp = timeval_to_ktime(tv);
+       hwts = skb_hwtstamps(skb);
+       hwts->hwtstamp = timeval_to_ktime(tv);
 
        /* push the skb */
        netif_rx(skb);
index e1626d9..30d79bf 100644 (file)
@@ -532,6 +532,7 @@ static int pcan_usb_pro_handle_canmsg(struct pcan_usb_pro_interface *usb_if,
        struct can_frame *can_frame;
        struct sk_buff *skb;
        struct timeval tv;
+       struct skb_shared_hwtstamps *hwts;
 
        skb = alloc_can_skb(netdev, &can_frame);
        if (!skb)
@@ -549,7 +550,8 @@ static int pcan_usb_pro_handle_canmsg(struct pcan_usb_pro_interface *usb_if,
                memcpy(can_frame->data, rx->data, can_frame->can_dlc);
 
        peak_usb_get_ts_tv(&usb_if->time_ref, le32_to_cpu(rx->ts32), &tv);
-       skb->tstamp = timeval_to_ktime(tv);
+       hwts = skb_hwtstamps(skb);
+       hwts->hwtstamp = timeval_to_ktime(tv);
 
        netif_rx(skb);
        netdev->stats.rx_packets++;
@@ -570,6 +572,7 @@ static int pcan_usb_pro_handle_error(struct pcan_usb_pro_interface *usb_if,
        u8 err_mask = 0;
        struct sk_buff *skb;
        struct timeval tv;
+       struct skb_shared_hwtstamps *hwts;
 
        /* nothing should be sent while in BUS_OFF state */
        if (dev->can.state == CAN_STATE_BUS_OFF)
@@ -664,7 +667,8 @@ static int pcan_usb_pro_handle_error(struct pcan_usb_pro_interface *usb_if,
        dev->can.state = new_state;
 
        peak_usb_get_ts_tv(&usb_if->time_ref, le32_to_cpu(er->ts32), &tv);
-       skb->tstamp = timeval_to_ktime(tv);
+       hwts = skb_hwtstamps(skb);
+       hwts->hwtstamp = timeval_to_ktime(tv);
        netif_rx(skb);
        netdev->stats.rx_packets++;
        netdev->stats.rx_bytes += can_frame->can_dlc;
index d04911d..47618e5 100644 (file)
@@ -813,6 +813,7 @@ static int __init ne_drv_probe(struct platform_device *pdev)
                dev->irq = irq[this_dev];
                dev->mem_end = bad[this_dev];
        }
+       SET_NETDEV_DEV(dev, &pdev->dev);
        err = do_ne_probe(dev);
        if (err) {
                free_netdev(dev);
index 2422099..4833b6a 100644 (file)
@@ -2957,9 +2957,13 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        skb_shinfo(skb)->nr_frags +
                        BDS_PER_TX_PKT +
                        NEXT_CNT_PER_TX_PKT(MAX_BDS_PER_TX_PKT))) {
-               bnx2x_fp_qstats(bp, txdata->parent_fp)->driver_xoff++;
-               netif_tx_stop_queue(txq);
-               BNX2X_ERR("BUG! Tx ring full when queue awake!\n");
+               /* Handle special storage cases separately */
+               if (txdata->tx_ring_size != 0) {
+                       BNX2X_ERR("BUG! Tx ring full when queue awake!\n");
+                       bnx2x_fp_qstats(bp, txdata->parent_fp)->driver_xoff++;
+                       netif_tx_stop_queue(txq);
+               }
+
                return NETDEV_TX_BUSY;
        }
 
index c65295d..6e5bdd1 100644 (file)
@@ -1702,7 +1702,7 @@ static int bnx2x_set_eee(struct net_device *dev, struct ethtool_eee *edata)
                                      SHMEM_EEE_ADV_STATUS_SHIFT);
        if ((advertised != (eee_cfg & SHMEM_EEE_ADV_STATUS_MASK))) {
                DP(BNX2X_MSG_ETHTOOL,
-                  "Direct manipulation of EEE advertisment is not supported\n");
+                  "Direct manipulation of EEE advertisement is not supported\n");
                return -EINVAL;
        }
 
index e2e45ee..f6cfdc6 100644 (file)
 #define LINK_20GTFD            LINK_STATUS_SPEED_AND_DUPLEX_20GTFD
 #define LINK_20GXFD            LINK_STATUS_SPEED_AND_DUPLEX_20GXFD
 
-
+#define LINK_UPDATE_MASK \
+                       (LINK_STATUS_SPEED_AND_DUPLEX_MASK | \
+                        LINK_STATUS_LINK_UP | \
+                        LINK_STATUS_PHYSICAL_LINK_FLAG | \
+                        LINK_STATUS_AUTO_NEGOTIATE_COMPLETE | \
+                        LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK | \
+                        LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK | \
+                        LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK | \
+                        LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE | \
+                        LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE)
 
 #define SFP_EEPROM_CON_TYPE_ADDR               0x2
        #define SFP_EEPROM_CON_TYPE_VAL_LC      0x7
@@ -3295,6 +3304,21 @@ static void bnx2x_serdes_deassert(struct bnx2x *bp, u8 port)
               DEFAULT_PHY_DEV_ADDR);
 }
 
+static void bnx2x_xgxs_specific_func(struct bnx2x_phy *phy,
+                                    struct link_params *params,
+                                    u32 action)
+{
+       struct bnx2x *bp = params->bp;
+       switch (action) {
+       case PHY_INIT:
+               /* Set correct devad */
+               REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + params->port*0x18, 0);
+               REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + params->port*0x18,
+                      phy->def_md_devad);
+               break;
+       }
+}
+
 static void bnx2x_xgxs_deassert(struct link_params *params)
 {
        struct bnx2x *bp = params->bp;
@@ -3309,10 +3333,8 @@ static void bnx2x_xgxs_deassert(struct link_params *params)
        REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
        udelay(500);
        REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
-
-       REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + port*0x18, 0);
-       REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
-              params->phy[INT_PHY].def_md_devad);
+       bnx2x_xgxs_specific_func(&params->phy[INT_PHY], params,
+                                PHY_INIT);
 }
 
 static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
@@ -3545,14 +3567,11 @@ static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy,
 static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
                                        struct link_params *params,
                                        struct link_vars *vars) {
-       u16 val16 = 0, lane, i;
+       u16 lane, i, cl72_ctrl, an_adv = 0;
+       u16 ucode_ver;
        struct bnx2x *bp = params->bp;
        static struct bnx2x_reg_set reg_set[] = {
                {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7},
-               {MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, 0},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0xff},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0x5555},
                {MDIO_PMA_DEVAD, MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0x0},
                {MDIO_WC_DEVAD, MDIO_WC_REG_RX66_CONTROL, 0x7415},
                {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x6190},
@@ -3565,12 +3584,19 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
                bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
                                 reg_set[i].val);
 
+       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+               MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &cl72_ctrl);
+       cl72_ctrl &= 0xf8ff;
+       cl72_ctrl |= 0x3800;
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+               MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, cl72_ctrl);
+
        /* Check adding advertisement for 1G KX */
        if (((vars->line_speed == SPEED_AUTO_NEG) &&
             (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
            (vars->line_speed == SPEED_1000)) {
                u32 addr = MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2;
-               val16 |= (1<<5);
+               an_adv |= (1<<5);
 
                /* Enable CL37 1G Parallel Detect */
                bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, addr, 0x1);
@@ -3580,11 +3606,14 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
             (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) ||
            (vars->line_speed ==  SPEED_10000)) {
                /* Check adding advertisement for 10G KR */
-               val16 |= (1<<7);
+               an_adv |= (1<<7);
                /* Enable 10G Parallel Detect */
+               CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+                                 MDIO_AER_BLOCK_AER_REG, 0);
+
                bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
                                 MDIO_WC_REG_PAR_DET_10G_CTRL, 1);
-
+               bnx2x_set_aer_mmd(params, phy);
                DP(NETIF_MSG_LINK, "Advertize 10G\n");
        }
 
@@ -3604,7 +3633,7 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
 
        /* Advertised speeds */
        bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
-                        MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, val16);
+                        MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, an_adv);
 
        /* Advertised and set FEC (Forward Error Correction) */
        bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
@@ -3628,9 +3657,10 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
        /* Set KR Autoneg Work-Around flag for Warpcore version older than D108
         */
        bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-                       MDIO_WC_REG_UC_INFO_B1_VERSION, &val16);
-       if (val16 < 0xd108) {
-               DP(NETIF_MSG_LINK, "Enable AN KR work-around\n");
+                       MDIO_WC_REG_UC_INFO_B1_VERSION, &ucode_ver);
+       if (ucode_ver < 0xd108) {
+               DP(NETIF_MSG_LINK, "Enable AN KR work-around. WC ver:0x%x\n",
+                              ucode_ver);
                vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
        }
        bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
@@ -3651,21 +3681,16 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
                                      struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
-       u16 i;
+       u16 val16, i, lane;
        static struct bnx2x_reg_set reg_set[] = {
                /* Disable Autoneg */
                {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7},
-               {MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0},
                {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
                        0x3f00},
                {MDIO_AN_DEVAD, MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, 0},
                {MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0},
                {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL3_UP1, 0x1},
                {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_MISC7, 0xa},
-               /* Disable CL36 PCS Tx */
-               {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0x0},
-               /* Double Wide Single Data Rate @ pll rate */
-               {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0xFFFF},
                /* Leave cl72 training enable, needed for KR */
                {MDIO_PMA_DEVAD,
                MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150,
@@ -3676,11 +3701,24 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
                bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
                                 reg_set[i].val);
 
-       /* Leave CL72 enabled */
-       bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
-                                MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
-                                0x3800);
+       lane = bnx2x_get_warpcore_lane(phy, params);
+       /* Global registers */
+       CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+                         MDIO_AER_BLOCK_AER_REG, 0);
+       /* Disable CL36 PCS Tx */
+       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+                       MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16);
+       val16 &= ~(0x0011 << lane);
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                        MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16);
 
+       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+                       MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16);
+       val16 |= (0x0303 << (lane << 1));
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                        MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16);
+       /* Restore AER */
+       bnx2x_set_aer_mmd(params, phy);
        /* Set speed via PMA/PMD register */
        bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
                         MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040);
@@ -4303,7 +4341,7 @@ static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,
                                      struct link_params *params)
 {
        struct bnx2x *bp = params->bp;
-       u16 val16;
+       u16 val16, lane;
        bnx2x_sfp_e3_set_transmitter(params, phy, 0);
        bnx2x_set_mdio_clk(bp, params->chip_id, params->port);
        bnx2x_set_aer_mmd(params, phy);
@@ -4340,6 +4378,30 @@ static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,
                         MDIO_WC_REG_XGXSBLK1_LANECTRL2,
                         val16 & 0xff00);
 
+       lane = bnx2x_get_warpcore_lane(phy, params);
+       /* Disable CL36 PCS Tx */
+       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+                       MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16);
+       val16 |= (0x11 << lane);
+       if (phy->flags & FLAGS_WC_DUAL_MODE)
+               val16 |= (0x22 << lane);
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                        MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16);
+
+       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+                       MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16);
+       val16 &= ~(0x0303 << (lane << 1));
+       val16 |= (0x0101 << (lane << 1));
+       if (phy->flags & FLAGS_WC_DUAL_MODE) {
+               val16 &= ~(0x0c0c << (lane << 1));
+               val16 |= (0x0404 << (lane << 1));
+       }
+
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                        MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16);
+       /* Restore AER */
+       bnx2x_set_aer_mmd(params, phy);
+
 }
 
 static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy,
@@ -6296,15 +6358,7 @@ static int bnx2x_update_link_down(struct link_params *params,
        vars->mac_type = MAC_TYPE_NONE;
 
        /* Update shared memory */
-       vars->link_status &= ~(LINK_STATUS_SPEED_AND_DUPLEX_MASK |
-                              LINK_STATUS_LINK_UP |
-                              LINK_STATUS_PHYSICAL_LINK_FLAG |
-                              LINK_STATUS_AUTO_NEGOTIATE_COMPLETE |
-                              LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK |
-                              LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK |
-                              LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK |
-                              LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE |
-                              LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE);
+       vars->link_status &= ~LINK_UPDATE_MASK;
        vars->line_speed = 0;
        bnx2x_update_mng(params, vars->link_status);
 
@@ -6452,6 +6506,7 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
        u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed;
        u8 active_external_phy = INT_PHY;
        vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
+       vars->link_status &= ~LINK_UPDATE_MASK;
        for (phy_index = INT_PHY; phy_index < params->num_phys;
              phy_index++) {
                phy_vars[phy_index].flow_ctrl = 0;
@@ -7579,7 +7634,7 @@ static void bnx2x_warpcore_power_module(struct link_params *params,
 static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
                                                 struct link_params *params,
                                                 u16 addr, u8 byte_cnt,
-                                                u8 *o_buf)
+                                                u8 *o_buf, u8 is_init)
 {
        int rc = 0;
        u8 i, j = 0, cnt = 0;
@@ -7596,10 +7651,10 @@ static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
        /* 4 byte aligned address */
        addr32 = addr & (~0x3);
        do {
-               if (cnt == I2C_WA_PWR_ITER) {
+               if ((!is_init) && (cnt == I2C_WA_PWR_ITER)) {
                        bnx2x_warpcore_power_module(params, phy, 0);
                        /* Note that 100us are not enough here */
-                       usleep_range(1000,1000);
+                       usleep_range(1000, 2000);
                        bnx2x_warpcore_power_module(params, phy, 1);
                }
                rc = bnx2x_bsc_read(params, phy, 0xa0, addr32, 0, byte_cnt,
@@ -7719,7 +7774,7 @@ int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
        break;
        case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
                rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, params, addr,
-                                                          byte_cnt, o_buf);
+                                                          byte_cnt, o_buf, 0);
        break;
        }
        return rc;
@@ -7923,6 +7978,7 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
 
 {
        u8 val;
+       int rc;
        struct bnx2x *bp = params->bp;
        u16 timeout;
        /* Initialization time after hot-plug may take up to 300ms for
@@ -7930,8 +7986,14 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
         */
 
        for (timeout = 0; timeout < 60; timeout++) {
-               if (bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val)
-                   == 0) {
+               if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
+                       rc = bnx2x_warpcore_read_sfp_module_eeprom(phy,
+                                                                  params, 1,
+                                                                  1, &val, 1);
+               else
+                       rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1,
+                                                         &val);
+               if (rc == 0) {
                        DP(NETIF_MSG_LINK,
                           "SFP+ module initialization took %d ms\n",
                           timeout * 5);
@@ -7939,7 +8001,8 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
                }
                usleep_range(5000, 10000);
        }
-       return -EINVAL;
+       rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val);
+       return rc;
 }
 
 static void bnx2x_8727_power_module(struct bnx2x *bp,
@@ -9878,7 +9941,7 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
                else
                        rc = bnx2x_8483x_disable_eee(phy, params, vars);
                if (rc) {
-                       DP(NETIF_MSG_LINK, "Failed to set EEE advertisment\n");
+                       DP(NETIF_MSG_LINK, "Failed to set EEE advertisement\n");
                        return rc;
                }
        } else {
@@ -10993,7 +11056,7 @@ static struct bnx2x_phy phy_xgxs = {
        .format_fw_ver  = (format_fw_ver_t)NULL,
        .hw_reset       = (hw_reset_t)NULL,
        .set_link_led   = (set_link_led_t)NULL,
-       .phy_specific_func = (phy_specific_func_t)NULL
+       .phy_specific_func = (phy_specific_func_t)bnx2x_xgxs_specific_func
 };
 static struct bnx2x_phy phy_warpcore = {
        .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
@@ -11465,6 +11528,11 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
                        phy->media_type = ETH_PHY_BASE_T;
                        break;
                case PORT_HW_CFG_NET_SERDES_IF_XFI:
+                       phy->supported &= (SUPPORTED_1000baseT_Full |
+                                          SUPPORTED_10000baseT_Full |
+                                          SUPPORTED_FIBRE |
+                                          SUPPORTED_Pause |
+                                          SUPPORTED_Asym_Pause);
                        phy->media_type = ETH_PHY_XFP_FIBER;
                        break;
                case PORT_HW_CFG_NET_SERDES_IF_SFI:
@@ -12919,7 +12987,7 @@ static u8 bnx2x_analyze_link_error(struct link_params *params,
                DP(NETIF_MSG_LINK, "Analyze TX Fault\n");
                break;
        default:
-               DP(NETIF_MSG_LINK, "Analyze UNKOWN\n");
+               DP(NETIF_MSG_LINK, "Analyze UNKNOWN\n");
        }
        DP(NETIF_MSG_LINK, "Link changed:[%x %x]->%x\n", vars->link_up,
           old_status, status);
index d5648fc..01611b3 100644 (file)
@@ -6794,8 +6794,9 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
 
        bnx2x_init_block(bp, BLOCK_DORQ, init_phase);
 
+       bnx2x_init_block(bp, BLOCK_BRB1, init_phase);
+
        if (CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) {
-               bnx2x_init_block(bp, BLOCK_BRB1, init_phase);
 
                if (IS_MF(bp))
                        low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246);
@@ -9544,10 +9545,13 @@ static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp)
  */
 static void __devinit bnx2x_prev_interrupted_dmae(struct bnx2x *bp)
 {
-       u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS);
-       if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) {
-               BNX2X_ERR("was error bit was found to be set in pglueb upon startup. Clearing");
-               REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, 1 << BP_FUNC(bp));
+       if (!CHIP_IS_E1x(bp)) {
+               u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS);
+               if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) {
+                       BNX2X_ERR("was error bit was found to be set in pglueb upon startup. Clearing");
+                       REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR,
+                              1 << BP_FUNC(bp));
+               }
        }
 }
 
@@ -11902,7 +11906,15 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
        /* disable FCOE L2 queue for E1x */
        if (CHIP_IS_E1x(bp))
                bp->flags |= NO_FCOE_FLAG;
-
+       /* disable FCOE for 57840 device, until FW supports it */
+       switch (ent->driver_data) {
+       case BCM57840_O:
+       case BCM57840_4_10:
+       case BCM57840_2_20:
+       case BCM57840_MFO:
+       case BCM57840_MF:
+               bp->flags |= NO_FCOE_FLAG;
+       }
 #endif
 
 
index 71971a1..614981c 100644 (file)
@@ -126,7 +126,7 @@ static inline int bnx2x_exe_queue_add(struct bnx2x *bp,
                /* Check if this request is ok */
                rc = o->validate(bp, o->owner, elem);
                if (rc) {
-                       BNX2X_ERR("Preamble failed: %d\n", rc);
+                       DP(BNX2X_MSG_SP, "Preamble failed: %d\n", rc);
                        goto free_and_exit;
                }
        }
index a4da893..378988b 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 604f4f8..0df1284 100644 (file)
@@ -3416,16 +3416,6 @@ static int adap_init0_config(struct adapter *adapter, int reset)
                         finicsum, cfcsum);
 
        /*
-        * 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;
-
-       /*
         * And now tell the firmware to use the configuration we just loaded.
         */
        caps_cmd.op_to_write =
@@ -3513,18 +3503,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 +3723,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 +3877,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 +3922,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 +3972,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 +4020,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 1b899fe..39bec73 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 32eec15..730ae2c 100644 (file)
@@ -2519,6 +2519,7 @@ int t4_fw_bye(struct adapter *adap, unsigned int mbox)
 {
        struct fw_bye_cmd c;
 
+       memset(&c, 0, sizeof(c));
        INIT_CMD(c, BYE, WRITE);
        return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
 }
@@ -2535,6 +2536,7 @@ int t4_early_init(struct adapter *adap, unsigned int mbox)
 {
        struct fw_initialize_cmd c;
 
+       memset(&c, 0, sizeof(c));
        INIT_CMD(c, INITIALIZE, WRITE);
        return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
 }
@@ -2551,6 +2553,7 @@ int t4_fw_reset(struct adapter *adap, unsigned int mbox, int reset)
 {
        struct fw_reset_cmd c;
 
+       memset(&c, 0, sizeof(c));
        INIT_CMD(c, RESET, WRITE);
        c.val = htonl(reset);
        return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
@@ -2828,7 +2831,7 @@ int t4_fixup_host_params(struct adapter *adap, unsigned int page_size,
                     HOSTPAGESIZEPF7(sge_hps));
 
        t4_set_reg_field(adap, SGE_CONTROL,
-                        INGPADBOUNDARY(INGPADBOUNDARY_MASK) |
+                        INGPADBOUNDARY_MASK |
                         EGRSTATUSPAGESIZE_MASK,
                         INGPADBOUNDARY(fl_align_log - 5) |
                         EGRSTATUSPAGESIZE(stat_len != 64));
@@ -3278,6 +3281,7 @@ int t4_identify_port(struct adapter *adap, unsigned int mbox, unsigned int viid,
 {
        struct fw_vi_enable_cmd c;
 
+       memset(&c, 0, sizeof(c));
        c.op_to_viid = htonl(FW_CMD_OP(FW_VI_ENABLE_CMD) | FW_CMD_REQUEST |
                             FW_CMD_EXEC | FW_VI_ENABLE_CMD_VIID(viid));
        c.ien_to_len16 = htonl(FW_VI_ENABLE_CMD_LED | FW_LEN16(c));
index 1d03dcd..19ac096 100644 (file)
@@ -1353,8 +1353,11 @@ static int gfar_restore(struct device *dev)
        struct gfar_private *priv = dev_get_drvdata(dev);
        struct net_device *ndev = priv->ndev;
 
-       if (!netif_running(ndev))
+       if (!netif_running(ndev)) {
+               netif_device_attach(ndev);
+
                return 0;
+       }
 
        gfar_init_bds(ndev);
        init_registers(ndev);
index b9db0e0..2e5daee 100644 (file)
@@ -478,7 +478,7 @@ static int gianfar_ptp_probe(struct platform_device *dev)
                pr_err("no resource\n");
                goto no_resource;
        }
-       if (request_resource(&ioport_resource, etsects->rsrc)) {
+       if (request_resource(&iomem_resource, etsects->rsrc)) {
                pr_err("resource busy\n");
                goto no_resource;
        }
index 56b20d1..116f0e9 100644 (file)
@@ -2673,6 +2673,9 @@ static int ixgbe_get_ts_info(struct net_device *dev,
        case ixgbe_mac_X540:
        case ixgbe_mac_82599EB:
                info->so_timestamping =
+                       SOF_TIMESTAMPING_TX_SOFTWARE |
+                       SOF_TIMESTAMPING_RX_SOFTWARE |
+                       SOF_TIMESTAMPING_SOFTWARE |
                        SOF_TIMESTAMPING_TX_HARDWARE |
                        SOF_TIMESTAMPING_RX_HARDWARE |
                        SOF_TIMESTAMPING_RAW_HARDWARE;
index f8064df..60ac46f 100644 (file)
@@ -1860,10 +1860,14 @@ jme_open(struct net_device *netdev)
        jme_clear_pm(jme);
        JME_NAPI_ENABLE(jme);
 
-       tasklet_enable(&jme->linkch_task);
-       tasklet_enable(&jme->txclean_task);
-       tasklet_hi_enable(&jme->rxclean_task);
-       tasklet_hi_enable(&jme->rxempty_task);
+       tasklet_init(&jme->linkch_task, jme_link_change_tasklet,
+                    (unsigned long) jme);
+       tasklet_init(&jme->txclean_task, jme_tx_clean_tasklet,
+                    (unsigned long) jme);
+       tasklet_init(&jme->rxclean_task, jme_rx_clean_tasklet,
+                    (unsigned long) jme);
+       tasklet_init(&jme->rxempty_task, jme_rx_empty_tasklet,
+                    (unsigned long) jme);
 
        rc = jme_request_irq(jme);
        if (rc)
@@ -1948,10 +1952,10 @@ jme_close(struct net_device *netdev)
 
        JME_NAPI_DISABLE(jme);
 
-       tasklet_disable(&jme->linkch_task);
-       tasklet_disable(&jme->txclean_task);
-       tasklet_disable(&jme->rxclean_task);
-       tasklet_disable(&jme->rxempty_task);
+       tasklet_kill(&jme->linkch_task);
+       tasklet_kill(&jme->txclean_task);
+       tasklet_kill(&jme->rxclean_task);
+       tasklet_kill(&jme->rxempty_task);
 
        jme_disable_rx_engine(jme);
        jme_disable_tx_engine(jme);
@@ -3079,22 +3083,6 @@ jme_init_one(struct pci_dev *pdev,
        tasklet_init(&jme->pcc_task,
                     jme_pcc_tasklet,
                     (unsigned long) jme);
-       tasklet_init(&jme->linkch_task,
-                    jme_link_change_tasklet,
-                    (unsigned long) jme);
-       tasklet_init(&jme->txclean_task,
-                    jme_tx_clean_tasklet,
-                    (unsigned long) jme);
-       tasklet_init(&jme->rxclean_task,
-                    jme_rx_clean_tasklet,
-                    (unsigned long) jme);
-       tasklet_init(&jme->rxempty_task,
-                    jme_rx_empty_tasklet,
-                    (unsigned long) jme);
-       tasklet_disable_nosync(&jme->linkch_task);
-       tasklet_disable_nosync(&jme->txclean_task);
-       tasklet_disable_nosync(&jme->rxclean_task);
-       tasklet_disable_nosync(&jme->rxempty_task);
        jme->dpi.cur = PCC_P1;
 
        jme->reg_ghc = 0;
index 9b9c2ac..d19a143 100644 (file)
@@ -4026,7 +4026,7 @@ static void __devexit skge_remove(struct pci_dev *pdev)
        dev0 = hw->dev[0];
        unregister_netdev(dev0);
 
-       tasklet_disable(&hw->phy_task);
+       tasklet_kill(&hw->phy_task);
 
        spin_lock_irq(&hw->hw_lock);
        hw->intr_mask = 0;
index 5d36795..b799ab1 100644 (file)
@@ -237,7 +237,7 @@ static int mlx4_en_dcbnl_ieee_setmaxrate(struct net_device *dev,
        if (err)
                return err;
 
-       memcpy(priv->maxrate, tmp, sizeof(*priv->maxrate));
+       memcpy(priv->maxrate, tmp, sizeof(priv->maxrate));
 
        return 0;
 }
index c10e3a6..b35094c 100644 (file)
@@ -143,7 +143,6 @@ void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv,
                mlx4_bf_free(mdev->dev, &ring->bf);
        mlx4_qp_remove(mdev->dev, &ring->qp);
        mlx4_qp_free(mdev->dev, &ring->qp);
-       mlx4_qp_release_range(mdev->dev, ring->qpn, 1);
        mlx4_en_unmap_buffer(&ring->wqres.buf);
        mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
        kfree(ring->bounce_buf);
@@ -712,7 +711,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
        if (bounce)
                tx_desc = mlx4_en_bounce_to_desc(priv, ring, index, desc_size);
 
-       if (ring->bf_enabled && desc_size <= MAX_BF && !bounce && !vlan_tag) {
+       if (ring->bf_enabled && desc_size <= MAX_BF && !bounce && !vlan_tx_tag_present(skb)) {
                *(__be32 *) (&tx_desc->ctrl.vlan_tag) |= cpu_to_be32(ring->doorbell_qpn);
                op_own |= htonl((bf_index & 0xffff) << 8);
                /* Ensure new descirptor hits memory
index 51c7649..b84a88b 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);
@@ -843,6 +837,18 @@ static void __iomem *mlx4_get_eq_uar(struct mlx4_dev *dev, struct mlx4_eq *eq)
        return priv->eq_table.uar_map[index] + 0x800 + 8 * (eq->eqn % 4);
 }
 
+static void mlx4_unmap_uar(struct mlx4_dev *dev)
+{
+       struct mlx4_priv *priv = mlx4_priv(dev);
+       int i;
+
+       for (i = 0; i < mlx4_num_eq_uar(dev); ++i)
+               if (priv->eq_table.uar_map[i]) {
+                       iounmap(priv->eq_table.uar_map[i]);
+                       priv->eq_table.uar_map[i] = NULL;
+               }
+}
+
 static int mlx4_create_eq(struct mlx4_dev *dev, int nent,
                          u8 intr, struct mlx4_eq *eq)
 {
@@ -1207,6 +1213,7 @@ err_out_unmap:
        mlx4_free_irqs(dev);
 
 err_out_bitmap:
+       mlx4_unmap_uar(dev);
        mlx4_bitmap_cleanup(&priv->eq_table.bitmap);
 
 err_out_free:
@@ -1231,10 +1238,7 @@ void mlx4_cleanup_eq_table(struct mlx4_dev *dev)
        if (!mlx4_is_slave(dev))
                mlx4_unmap_clr_int(dev);
 
-       for (i = 0; i < mlx4_num_eq_uar(dev); ++i)
-               if (priv->eq_table.uar_map[i])
-                       iounmap(priv->eq_table.uar_map[i]);
-
+       mlx4_unmap_uar(dev);
        mlx4_bitmap_cleanup(&priv->eq_table.bitmap);
 
        kfree(priv->eq_table.uar_map);
index 80df2ab..2aa80af 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 926c911..b05705f 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 318fee9..69e0197 100644 (file)
@@ -5407,8 +5407,8 @@ static int netdev_close(struct net_device *dev)
                /* Delay for receive task to stop scheduling itself. */
                msleep(2000 / HZ);
 
-               tasklet_disable(&hw_priv->rx_tasklet);
-               tasklet_disable(&hw_priv->tx_tasklet);
+               tasklet_kill(&hw_priv->rx_tasklet);
+               tasklet_kill(&hw_priv->tx_tasklet);
                free_irq(dev->irq, hw_priv->dev);
 
                transmit_cleanup(hw_priv, 0);
@@ -5459,8 +5459,10 @@ static int prepare_hardware(struct net_device *dev)
        rc = request_irq(dev->irq, netdev_intr, IRQF_SHARED, dev->name, dev);
        if (rc)
                return rc;
-       tasklet_enable(&hw_priv->rx_tasklet);
-       tasklet_enable(&hw_priv->tx_tasklet);
+       tasklet_init(&hw_priv->rx_tasklet, rx_proc_task,
+                    (unsigned long) hw_priv);
+       tasklet_init(&hw_priv->tx_tasklet, tx_proc_task,
+                    (unsigned long) hw_priv);
 
        hw->promiscuous = 0;
        hw->all_multi = 0;
@@ -7033,16 +7035,6 @@ static int __devinit pcidev_init(struct pci_dev *pdev,
        spin_lock_init(&hw_priv->hwlock);
        mutex_init(&hw_priv->lock);
 
-       /* tasklet is enabled. */
-       tasklet_init(&hw_priv->rx_tasklet, rx_proc_task,
-               (unsigned long) hw_priv);
-       tasklet_init(&hw_priv->tx_tasklet, tx_proc_task,
-               (unsigned long) hw_priv);
-
-       /* tasklet_enable will decrement the atomic counter. */
-       tasklet_disable(&hw_priv->rx_tasklet);
-       tasklet_disable(&hw_priv->tx_tasklet);
-
        for (i = 0; i < TOTAL_PORT_NUM; i++)
                init_waitqueue_head(&hw_priv->counter[i].counter);
 
index 53743f7..af8b414 100644 (file)
@@ -1524,6 +1524,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev)
                                  pldat->dma_buff_base_p);
        free_irq(ndev->irq, ndev);
        iounmap(pldat->net_base);
+       mdiobus_unregister(pldat->mii_bus);
        mdiobus_free(pldat->mii_bus);
        clk_disable(pldat->clk);
        clk_put(pldat->clk);
index b2a94d0..4c4fe5b 100644 (file)
@@ -339,26 +339,6 @@ static void pch_gbe_wait_clr_bit(void *reg, u32 bit)
 }
 
 /**
- * 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
  * @addr:   Pointer to the MAC address
@@ -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);
                }
@@ -1971,12 +1930,12 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)
        struct net_device *netdev = adapter->netdev;
        struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring;
        struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring;
-       int err;
+       int err = -EINVAL;
 
        /* Ensure we have a valid MAC */
        if (!is_valid_ether_addr(adapter->hw.mac.addr)) {
                pr_err("Error: Invalid MAC address\n");
-               return -EINVAL;
+               goto out;
        }
 
        /* hardware has been reset, we need to reload some things */
@@ -1989,18 +1948,19 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)
 
        err = pch_gbe_request_irq(adapter);
        if (err) {
-               pr_err("Error: can't bring device up\n");
-               return err;
+               pr_err("Error: can't bring device up - irq request failed\n");
+               goto out;
        }
        err = pch_gbe_alloc_rx_buffers_pool(adapter, rx_ring, rx_ring->count);
        if (err) {
-               pr_err("Error: can't bring device up\n");
-               return err;
+               pr_err("Error: can't bring device up - alloc rx buffers pool failed\n");
+               goto freeirq;
        }
        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);
 
@@ -2009,6 +1969,11 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)
        netif_start_queue(adapter->netdev);
 
        return 0;
+
+freeirq:
+       pch_gbe_free_irq(adapter);
+out:
+       return err;
 }
 
 /**
@@ -2405,7 +2370,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 +2386,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 df09b1c..6407d0d 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 1c81825..609125a 100644 (file)
@@ -979,17 +979,6 @@ static void cp_init_hw (struct cp_private *cp)
        cpw32_f (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0)));
        cpw32_f (MAC0 + 4, le32_to_cpu (*(__le32 *) (dev->dev_addr + 4)));
 
-       cpw32_f(HiTxRingAddr, 0);
-       cpw32_f(HiTxRingAddr + 4, 0);
-
-       ring_dma = cp->ring_dma;
-       cpw32_f(RxRingAddr, ring_dma & 0xffffffff);
-       cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16);
-
-       ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE;
-       cpw32_f(TxRingAddr, ring_dma & 0xffffffff);
-       cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16);
-
        cp_start_hw(cp);
        cpw8(TxThresh, 0x06); /* XXX convert magic num to a constant */
 
@@ -1003,6 +992,17 @@ static void cp_init_hw (struct cp_private *cp)
 
        cpw8(Config5, cpr8(Config5) & PMEStatus);
 
+       cpw32_f(HiTxRingAddr, 0);
+       cpw32_f(HiTxRingAddr + 4, 0);
+
+       ring_dma = cp->ring_dma;
+       cpw32_f(RxRingAddr, ring_dma & 0xffffffff);
+       cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16);
+
+       ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE;
+       cpw32_f(TxRingAddr, ring_dma & 0xffffffff);
+       cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16);
+
        cpw16(MultiIntr, 0);
 
        cpw8_f(Cfg9346, Cfg9346_Lock);
@@ -1060,17 +1060,22 @@ static int cp_init_rings (struct cp_private *cp)
 
 static int cp_alloc_rings (struct cp_private *cp)
 {
+       struct device *d = &cp->pdev->dev;
        void *mem;
+       int rc;
 
-       mem = dma_alloc_coherent(&cp->pdev->dev, CP_RING_BYTES,
-                                &cp->ring_dma, GFP_KERNEL);
+       mem = dma_alloc_coherent(d, CP_RING_BYTES, &cp->ring_dma, GFP_KERNEL);
        if (!mem)
                return -ENOMEM;
 
        cp->rx_ring = mem;
        cp->tx_ring = &cp->rx_ring[CP_RX_RING_SIZE];
 
-       return cp_init_rings(cp);
+       rc = cp_init_rings(cp);
+       if (rc < 0)
+               dma_free_coherent(d, CP_RING_BYTES, cp->rx_ring, cp->ring_dma);
+
+       return rc;
 }
 
 static void cp_clean_rings (struct cp_private *cp)
index e7ff886..927aa33 100644 (file)
@@ -3827,6 +3827,8 @@ static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
        void __iomem *ioaddr = tp->mmio_addr;
 
        switch (tp->mac_version) {
+       case RTL_GIGA_MAC_VER_25:
+       case RTL_GIGA_MAC_VER_26:
        case RTL_GIGA_MAC_VER_29:
        case RTL_GIGA_MAC_VER_30:
        case RTL_GIGA_MAC_VER_32:
@@ -4519,6 +4521,9 @@ static void rtl_set_rx_mode(struct net_device *dev)
                mc_filter[1] = swab32(data);
        }
 
+       if (tp->mac_version == RTL_GIGA_MAC_VER_35)
+               mc_filter[1] = mc_filter[0] = 0xffffffff;
+
        RTL_W32(MAR0 + 4, mc_filter[1]);
        RTL_W32(MAR0 + 0, mc_filter[0]);
 
index fb9f6b3..edf5edb 100644 (file)
@@ -2479,7 +2479,7 @@ static int sis900_resume(struct pci_dev *pci_dev)
        netif_start_queue(net_dev);
 
        /* Workaround for EDB */
-       sis900_set_mode(ioaddr, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
+       sis900_set_mode(sis_priv, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
 
        /* Enable all known interrupts by setting the interrupt mask. */
        sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE);
index 62d1baf..c53c0f4 100644 (file)
@@ -2110,7 +2110,7 @@ static void __devinit smsc911x_read_mac_address(struct net_device *dev)
 static int __devinit smsc911x_init(struct net_device *dev)
 {
        struct smsc911x_data *pdata = netdev_priv(dev);
-       unsigned int byte_test;
+       unsigned int byte_test, mask;
        unsigned int to = 100;
 
        SMSC_TRACE(pdata, probe, "Driver Parameters:");
@@ -2130,9 +2130,22 @@ static int __devinit smsc911x_init(struct net_device *dev)
        /*
         * poll the READY bit in PMT_CTRL. Any other access to the device is
         * forbidden while this bit isn't set. Try for 100ms
+        *
+        * Note that this test is done before the WORD_SWAP register is
+        * programmed. So in some configurations the READY bit is at 16 before
+        * WORD_SWAP is written to. This issue is worked around by waiting
+        * until either bit 0 or bit 16 gets set in PMT_CTRL.
+        *
+        * SMSC has confirmed that checking bit 16 (marked as reserved in
+        * the datasheet) is fine since these bits "will either never be set
+        * or can only go high after READY does (so also indicate the device
+        * is ready)".
         */
-       while (!(smsc911x_reg_read(pdata, PMT_CTRL) & PMT_CTRL_READY_) && --to)
+
+       mask = PMT_CTRL_READY_ | swahw32(PMT_CTRL_READY_);
+       while (!(smsc911x_reg_read(pdata, PMT_CTRL) & mask) && --to)
                udelay(1000);
+
        if (to == 0) {
                pr_err("Device not READY in 100ms aborting\n");
                return -ENODEV;
index b26cbda..2c41894 100644 (file)
@@ -5,7 +5,7 @@
 config NET_VENDOR_TI
        bool "Texas Instruments (TI) devices"
        default y
-       depends on PCI || EISA || AR7 || (ARM && (ARCH_DAVINCI || ARCH_OMAP3))
+       depends on PCI || EISA || AR7 || (ARM && (ARCH_DAVINCI || ARCH_OMAP3 || SOC_AM33XX))
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
          and read the Ethernet-HOWTO, available from
index 4e2a162..66e025a 100644 (file)
@@ -917,7 +917,7 @@ static int tile_net_setup_interrupts(struct net_device *dev)
        ingress_irq = rc;
        tile_irq_activate(ingress_irq, TILE_IRQ_PERCPU);
        rc = request_irq(ingress_irq, tile_net_handle_ingress_irq,
-                        0, NULL, NULL);
+                        0, "tile_net", NULL);
        if (rc != 0) {
                netdev_err(dev, "request_irq failed: %d\n", rc);
                destroy_irq(ingress_irq);
@@ -1334,11 +1334,11 @@ static int tso_count_edescs(struct sk_buff *skb)
 {
        struct skb_shared_info *sh = skb_shinfo(skb);
        unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-       unsigned int data_len = skb->data_len + skb->hdr_len - sh_len;
+       unsigned int data_len = skb->len - sh_len;
        unsigned int p_len = sh->gso_size;
        long f_id = -1;    /* id of the current fragment */
-       long f_size = skb->hdr_len;  /* size of the current fragment */
-       long f_used = sh_len;  /* bytes used from the current fragment */
+       long f_size = skb_headlen(skb) - sh_len;  /* current fragment size */
+       long f_used = 0;  /* bytes used from the current fragment */
        long n;            /* size of the current piece of payload */
        int num_edescs = 0;
        int segment;
@@ -1353,7 +1353,7 @@ static int tso_count_edescs(struct sk_buff *skb)
                        /* Advance as needed. */
                        while (f_used >= f_size) {
                                f_id++;
-                               f_size = sh->frags[f_id].size;
+                               f_size = skb_frag_size(&sh->frags[f_id]);
                                f_used = 0;
                        }
 
@@ -1384,13 +1384,13 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers,
        struct iphdr *ih;
        struct tcphdr *th;
        unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-       unsigned int data_len = skb->data_len + skb->hdr_len - sh_len;
+       unsigned int data_len = skb->len - sh_len;
        unsigned char *data = skb->data;
        unsigned int ih_off, th_off, p_len;
        unsigned int isum_seed, tsum_seed, id, seq;
        long f_id = -1;    /* id of the current fragment */
-       long f_size = skb->hdr_len;  /* size of the current fragment */
-       long f_used = sh_len;  /* bytes used from the current fragment */
+       long f_size = skb_headlen(skb) - sh_len;  /* current fragment size */
+       long f_used = 0;  /* bytes used from the current fragment */
        long n;            /* size of the current piece of payload */
        int segment;
 
@@ -1405,7 +1405,7 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers,
        isum_seed = ((0xFFFF - ih->check) +
                     (0xFFFF - ih->tot_len) +
                     (0xFFFF - ih->id));
-       tsum_seed = th->check + (0xFFFF ^ htons(sh_len + data_len));
+       tsum_seed = th->check + (0xFFFF ^ htons(skb->len));
        id = ntohs(ih->id);
        seq = ntohl(th->seq);
 
@@ -1444,7 +1444,7 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers,
                        /* Advance as needed. */
                        while (f_used >= f_size) {
                                f_id++;
-                               f_size = sh->frags[f_id].size;
+                               f_size = skb_frag_size(&sh->frags[f_id]);
                                f_used = 0;
                        }
 
@@ -1478,14 +1478,14 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue,
        struct tile_net_priv *priv = netdev_priv(dev);
        struct skb_shared_info *sh = skb_shinfo(skb);
        unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-       unsigned int data_len = skb->data_len + skb->hdr_len - sh_len;
+       unsigned int data_len = skb->len - sh_len;
        unsigned int p_len = sh->gso_size;
        gxio_mpipe_edesc_t edesc_head = { { 0 } };
        gxio_mpipe_edesc_t edesc_body = { { 0 } };
        long f_id = -1;    /* id of the current fragment */
-       long f_size = skb->hdr_len;  /* size of the current fragment */
-       long f_used = sh_len;  /* bytes used from the current fragment */
-       void *f_data = skb->data;
+       long f_size = skb_headlen(skb) - sh_len;  /* current fragment size */
+       long f_used = 0;  /* bytes used from the current fragment */
+       void *f_data = skb->data + sh_len;
        long n;            /* size of the current piece of payload */
        unsigned long tx_packets = 0, tx_bytes = 0;
        unsigned int csum_start;
@@ -1516,15 +1516,18 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue,
 
                /* Egress the payload. */
                while (p_used < p_len) {
+                       void *va;
 
                        /* Advance as needed. */
                        while (f_used >= f_size) {
                                f_id++;
-                               f_size = sh->frags[f_id].size;
-                               f_used = 0;
+                               f_size = skb_frag_size(&sh->frags[f_id]);
                                f_data = tile_net_frag_buf(&sh->frags[f_id]);
+                               f_used = 0;
                        }
 
+                       va = f_data + f_used;
+
                        /* Use bytes from the current fragment. */
                        n = p_len - p_used;
                        if (n > f_size - f_used)
@@ -1533,7 +1536,7 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue,
                        p_used += n;
 
                        /* Egress a piece of the payload. */
-                       edesc_body.va = va_to_tile_io_addr(f_data) + f_used;
+                       edesc_body.va = va_to_tile_io_addr(va);
                        edesc_body.xfer_size = n;
                        edesc_body.bound = !(p_used < p_len);
                        gxio_mpipe_equeue_put_at(equeue, edesc_body, slot);
index 0793299..a788501 100644 (file)
@@ -894,6 +894,8 @@ out:
        return IRQ_HANDLED;
 }
 
+static void axienet_dma_err_handler(unsigned long data);
+
 /**
  * axienet_open - Driver open routine.
  * @ndev:      Pointer to net_device structure
@@ -942,6 +944,10 @@ static int axienet_open(struct net_device *ndev)
                phy_start(lp->phy_dev);
        }
 
+       /* Enable tasklets for Axi DMA error handling */
+       tasklet_init(&lp->dma_err_tasklet, axienet_dma_err_handler,
+                    (unsigned long) lp);
+
        /* Enable interrupts for Axi DMA Tx */
        ret = request_irq(lp->tx_irq, axienet_tx_irq, 0, ndev->name, ndev);
        if (ret)
@@ -950,8 +956,7 @@ static int axienet_open(struct net_device *ndev)
        ret = request_irq(lp->rx_irq, axienet_rx_irq, 0, ndev->name, ndev);
        if (ret)
                goto err_rx_irq;
-       /* Enable tasklets for Axi DMA error handling */
-       tasklet_enable(&lp->dma_err_tasklet);
+
        return 0;
 
 err_rx_irq:
@@ -960,6 +965,7 @@ err_tx_irq:
        if (lp->phy_dev)
                phy_disconnect(lp->phy_dev);
        lp->phy_dev = NULL;
+       tasklet_kill(&lp->dma_err_tasklet);
        dev_err(lp->dev, "request_irq() failed\n");
        return ret;
 }
@@ -990,7 +996,7 @@ static int axienet_stop(struct net_device *ndev)
        axienet_setoptions(ndev, lp->options &
                           ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
 
-       tasklet_disable(&lp->dma_err_tasklet);
+       tasklet_kill(&lp->dma_err_tasklet);
 
        free_irq(lp->tx_irq, ndev);
        free_irq(lp->rx_irq, ndev);
@@ -1613,10 +1619,6 @@ static int __devinit axienet_of_probe(struct platform_device *op)
                goto err_iounmap_2;
        }
 
-       tasklet_init(&lp->dma_err_tasklet, axienet_dma_err_handler,
-                    (unsigned long) lp);
-       tasklet_disable(&lp->dma_err_tasklet);
-
        return 0;
 
 err_iounmap_2:
index 98934bd..477d672 100644 (file)
@@ -1102,10 +1102,12 @@ static int init_queues(struct port *port)
 {
        int i;
 
-       if (!ports_open)
-               if (!(dma_pool = dma_pool_create(DRV_NAME, NULL,
-                                                POOL_ALLOC_SIZE, 32, 0)))
+       if (!ports_open) {
+               dma_pool = dma_pool_create(DRV_NAME, &port->netdev->dev,
+                                          POOL_ALLOC_SIZE, 32, 0);
+               if (!dma_pool)
                        return -ENOMEM;
+       }
 
        if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL,
                                              &port->desc_tab_phys)))
index 5039f08..43e9ab4 100644 (file)
@@ -222,7 +222,7 @@ static void sirdev_config_fsm(struct work_struct *work)
                        break;
 
                case SIRDEV_STATE_DONGLE_SPEED:
-                       if (dev->dongle_drv->reset) {
+                       if (dev->dongle_drv->set_speed) {
                                ret = dev->dongle_drv->set_speed(dev, fsm->param);
                                if (ret < 0) {
                                        fsm->result = ret;
index 983bbf4..961f0b2 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 426674d..9645e38 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 899274f..2ed1140 100644 (file)
@@ -185,17 +185,20 @@ static int __devinit mdio_gpio_probe(struct platform_device *pdev)
 {
        struct mdio_gpio_platform_data *pdata;
        struct mii_bus *new_bus;
-       int ret;
+       int ret, bus_id;
 
-       if (pdev->dev.of_node)
+       if (pdev->dev.of_node) {
                pdata = mdio_gpio_of_get_data(pdev);
-       else
+               bus_id = of_alias_get_id(pdev->dev.of_node, "mdio-gpio");
+       } else {
                pdata = pdev->dev.platform_data;
+               bus_id = pdev->id;
+       }
 
        if (!pdata)
                return -ENODEV;
 
-       new_bus = mdio_gpio_bus_init(&pdev->dev, pdata, pdev->id);
+       new_bus = mdio_gpio_bus_init(&pdev->dev, pdata, bus_id);
        if (!new_bus)
                return -ENODEV;
 
index d44cca3..ad86660 100644 (file)
@@ -1794,10 +1794,12 @@ static void team_setup(struct net_device *dev)
 
        dev->features |= NETIF_F_LLTX;
        dev->features |= NETIF_F_GRO;
-       dev->hw_features = NETIF_F_HW_VLAN_TX |
+       dev->hw_features = TEAM_VLAN_FEATURES |
+                          NETIF_F_HW_VLAN_TX |
                           NETIF_F_HW_VLAN_RX |
                           NETIF_F_HW_VLAN_FILTER;
 
+       dev->hw_features &= ~(NETIF_F_ALL_CSUM & ~NETIF_F_HW_CSUM);
        dev->features |= dev->hw_features;
 }
 
index 9db0171..c5db428 100644 (file)
@@ -29,8 +29,8 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb)
                        if (last) {
                                skb2 = skb_clone(skb, GFP_ATOMIC);
                                if (skb2) {
-                                       ret = team_dev_queue_xmit(team, last,
-                                                                 skb2);
+                                       ret = !team_dev_queue_xmit(team, last,
+                                                                  skb2);
                                        if (!sum_ret)
                                                sum_ret = ret;
                                }
@@ -39,7 +39,7 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb)
                }
        }
        if (last) {
-               ret = team_dev_queue_xmit(team, last, skb);
+               ret = !team_dev_queue_xmit(team, last, skb);
                if (!sum_ret)
                        sum_ret = ret;
        }
index c81e278..08d55b6 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/usb/cdc.h>
 #include <linux/usb/usbnet.h>
 #include <linux/gfp.h>
+#include <linux/if_vlan.h>
 
 
 /*
@@ -92,7 +93,7 @@ static int eem_bind(struct usbnet *dev, struct usb_interface *intf)
 
        /* no jumbogram (16K) support for now */
 
-       dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN;
+       dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN + VLAN_HLEN;
        dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
 
        return 0;
index a03de71..d012982 100644 (file)
@@ -592,6 +592,32 @@ static const struct usb_device_id  products [] = {
        .driver_info            = 0,
 },
 
+/* Novatel USB551L and MC551 - handled by qmi_wwan */
+{
+       .match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
+                | USB_DEVICE_ID_MATCH_PRODUCT
+                | USB_DEVICE_ID_MATCH_INT_INFO,
+       .idVendor               = NOVATEL_VENDOR_ID,
+       .idProduct              = 0xB001,
+       .bInterfaceClass        = USB_CLASS_COMM,
+       .bInterfaceSubClass     = USB_CDC_SUBCLASS_ETHERNET,
+       .bInterfaceProtocol     = USB_CDC_PROTO_NONE,
+       .driver_info = 0,
+},
+
+/* Novatel E362 - handled by qmi_wwan */
+{
+       .match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
+                | USB_DEVICE_ID_MATCH_PRODUCT
+                | USB_DEVICE_ID_MATCH_INT_INFO,
+       .idVendor               = NOVATEL_VENDOR_ID,
+       .idProduct              = 0x9010,
+       .bInterfaceClass        = USB_CLASS_COMM,
+       .bInterfaceSubClass     = USB_CDC_SUBCLASS_ETHERNET,
+       .bInterfaceProtocol     = USB_CDC_PROTO_NONE,
+       .driver_info = 0,
+},
+
 /*
  * WHITELIST!!!
  *
@@ -604,21 +630,6 @@ static const struct usb_device_id  products [] = {
  * because of bugs/quirks in a given product (like Zaurus, above).
  */
 {
-       /* Novatel USB551L */
-       /* This match must come *before* the generic CDC-ETHER match so that
-        * we get FLAG_WWAN set on the device, since it's descriptors are
-        * generic CDC-ETHER.
-        */
-       .match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
-                | USB_DEVICE_ID_MATCH_PRODUCT
-                | USB_DEVICE_ID_MATCH_INT_INFO,
-       .idVendor               = NOVATEL_VENDOR_ID,
-       .idProduct              = 0xB001,
-       .bInterfaceClass        = USB_CLASS_COMM,
-       .bInterfaceSubClass     = USB_CDC_SUBCLASS_ETHERNET,
-       .bInterfaceProtocol     = USB_CDC_PROTO_NONE,
-       .driver_info = (unsigned long)&wwan_info,
-}, {
        /* ZTE (Vodafone) K3805-Z */
        .match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
                 | USB_DEVICE_ID_MATCH_PRODUCT
index 4cd582a..74fab1a 100644 (file)
@@ -540,10 +540,12 @@ advance:
            (ctx->ether_desc == NULL) || (ctx->control != intf))
                goto error;
 
-       /* claim interfaces, if any */
-       temp = usb_driver_claim_interface(driver, ctx->data, dev);
-       if (temp)
-               goto error;
+       /* claim data interface, if different from control */
+       if (ctx->data != ctx->control) {
+               temp = usb_driver_claim_interface(driver, ctx->data, dev);
+               if (temp)
+                       goto error;
+       }
 
        iface_no = ctx->data->cur_altsetting->desc.bInterfaceNumber;
 
@@ -623,6 +625,10 @@ static void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
 
        tasklet_kill(&ctx->bh);
 
+       /* handle devices with combined control and data interface */
+       if (ctx->control == ctx->data)
+               ctx->data = NULL;
+
        /* disconnect master --> disconnect slave */
        if (intf == ctx->control && ctx->data) {
                usb_set_intfdata(ctx->data, NULL);
@@ -1245,6 +1251,14 @@ static const struct usb_device_id cdc_devs[] = {
          .driver_info = (unsigned long) &wwan_info,
        },
 
+       /* Huawei NCM devices disguised as vendor specific */
+       { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x16),
+         .driver_info = (unsigned long)&wwan_info,
+       },
+       { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x46),
+         .driver_info = (unsigned long)&wwan_info,
+       },
+
        /* Generic CDC-NCM devices */
        { USB_INTERFACE_INFO(USB_CLASS_COMM,
                USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
index a28a983..534d8be 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 6883c37..1ea91f4 100644 (file)
@@ -369,18 +369,74 @@ static const struct usb_device_id products[] = {
                USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff),
                .driver_info        = (unsigned long)&qmi_wwan_info,
        },
+       {       /* Novatel USB551L and MC551 */
+               USB_DEVICE_AND_INTERFACE_INFO(0x1410, 0xb001,
+                                             USB_CLASS_COMM,
+                                             USB_CDC_SUBCLASS_ETHERNET,
+                                             USB_CDC_PROTO_NONE),
+               .driver_info        = (unsigned long)&qmi_wwan_info,
+       },
+       {       /* Novatel E362 */
+               USB_DEVICE_AND_INTERFACE_INFO(0x1410, 0x9010,
+                                             USB_CLASS_COMM,
+                                             USB_CDC_SUBCLASS_ETHERNET,
+                                             USB_CDC_PROTO_NONE),
+               .driver_info        = (unsigned long)&qmi_wwan_info,
+       },
 
        /* 3. Combined interface devices matching on interface number */
+       {QMI_FIXED_INTF(0x12d1, 0x140c, 1)},    /* Huawei E173 */
+       {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 7479a57..362cb8c 100644 (file)
@@ -184,7 +184,7 @@ static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
        /* set the address, index & direction (read from PHY) */
        phy_id &= dev->mii.phy_id_mask;
        idx &= dev->mii.reg_num_mask;
-       addr = (phy_id << 11) | (idx << 6) | MII_READ_;
+       addr = (phy_id << 11) | (idx << 6) | MII_READ_ | MII_BUSY_;
        ret = smsc95xx_write_reg(dev, MII_ADDR, addr);
        check_warn_goto_done(ret, "Error writing MII_ADDR");
 
@@ -221,7 +221,7 @@ static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
        /* set the address, index & direction (write to PHY) */
        phy_id &= dev->mii.phy_id_mask;
        idx &= dev->mii.reg_num_mask;
-       addr = (phy_id << 11) | (idx << 6) | MII_WRITE_;
+       addr = (phy_id << 11) | (idx << 6) | MII_WRITE_ | MII_BUSY_;
        ret = smsc95xx_write_reg(dev, MII_ADDR, addr);
        check_warn_goto_done(ret, "Error writing MII_ADDR");
 
@@ -1344,6 +1344,7 @@ static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev,
                } else {
                        u32 csum_preamble = smsc95xx_calc_csum_preamble(skb);
                        skb_push(skb, 4);
+                       cpu_to_le32s(&csum_preamble);
                        memcpy(skb->data, &csum_preamble, 4);
                }
        }
index f9819d1..edb81ed 100644 (file)
@@ -359,10 +359,12 @@ static enum skb_state defer_bh(struct usbnet *dev, struct sk_buff *skb,
 void usbnet_defer_kevent (struct usbnet *dev, int work)
 {
        set_bit (work, &dev->flags);
-       if (!schedule_work (&dev->kevent))
-               netdev_err(dev->net, "kevent %d may have been dropped\n", work);
-       else
+       if (!schedule_work (&dev->kevent)) {
+               if (net_ratelimit())
+                       netdev_err(dev->net, "kevent %d may have been dropped\n", work);
+       } else {
                netdev_dbg(dev->net, "kevent %d scheduled\n", work);
+       }
 }
 EXPORT_SYMBOL_GPL(usbnet_defer_kevent);
 
@@ -1158,6 +1160,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
                usb_anchor_urb(urb, &dev->deferred);
                /* no use to process more packets */
                netif_stop_queue(net);
+               usb_put_urb(urb);
                spin_unlock_irqrestore(&dev->txq.lock, flags);
                netdev_dbg(dev->net, "Delaying transmission for resumption\n");
                goto deferred;
@@ -1310,6 +1313,8 @@ void usbnet_disconnect (struct usb_interface *intf)
 
        cancel_work_sync(&dev->kevent);
 
+       usb_scuttle_anchored_urbs(&dev->deferred);
+
        if (dev->driver_info->unbind)
                dev->driver_info->unbind (dev, intf);
 
index ce9d4f2..0ae1bcc 100644 (file)
@@ -744,28 +744,43 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx,
 
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+               u32 buf_size;
 
-               tbi = tq->buf_info + tq->tx_ring.next2fill;
-               tbi->map_type = VMXNET3_MAP_PAGE;
-               tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag,
-                                                0, skb_frag_size(frag),
-                                                DMA_TO_DEVICE);
+               buf_offset = 0;
+               len = skb_frag_size(frag);
+               while (len) {
+                       tbi = tq->buf_info + tq->tx_ring.next2fill;
+                       if (len < VMXNET3_MAX_TX_BUF_SIZE) {
+                               buf_size = len;
+                               dw2 |= len;
+                       } else {
+                               buf_size = VMXNET3_MAX_TX_BUF_SIZE;
+                               /* spec says that for TxDesc.len, 0 == 2^14 */
+                       }
+                       tbi->map_type = VMXNET3_MAP_PAGE;
+                       tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag,
+                                                        buf_offset, buf_size,
+                                                        DMA_TO_DEVICE);
 
-               tbi->len = skb_frag_size(frag);
+                       tbi->len = buf_size;
 
-               gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
-               BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
+                       gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
+                       BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
 
-               gdesc->txd.addr = cpu_to_le64(tbi->dma_addr);
-               gdesc->dword[2] = cpu_to_le32(dw2 | skb_frag_size(frag));
-               gdesc->dword[3] = 0;
+                       gdesc->txd.addr = cpu_to_le64(tbi->dma_addr);
+                       gdesc->dword[2] = cpu_to_le32(dw2);
+                       gdesc->dword[3] = 0;
 
-               dev_dbg(&adapter->netdev->dev,
-                       "txd[%u]: 0x%llu %u %u\n",
-                       tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr),
-                       le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]);
-               vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
-               dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
+                       dev_dbg(&adapter->netdev->dev,
+                               "txd[%u]: 0x%llu %u %u\n",
+                               tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr),
+                               le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]);
+                       vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
+                       dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
+
+                       len -= buf_size;
+                       buf_offset += buf_size;
+               }
        }
 
        ctx->eop_txd = gdesc;
@@ -886,6 +901,18 @@ vmxnet3_prepare_tso(struct sk_buff *skb,
        }
 }
 
+static int txd_estimate(const struct sk_buff *skb)
+{
+       int count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + 1;
+       int i;
+
+       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+               const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+
+               count += VMXNET3_TXD_NEEDED(skb_frag_size(frag));
+       }
+       return count;
+}
 
 /*
  * Transmits a pkt thru a given tq
@@ -914,9 +941,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
        union Vmxnet3_GenericDesc tempTxDesc;
 #endif
 
-       /* conservatively estimate # of descriptors to use */
-       count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) +
-               skb_shinfo(skb)->nr_frags + 1;
+       count = txd_estimate(skb);
 
        ctx.ipv4 = (vlan_get_protocol(skb) == cpu_to_be16(ETH_P_IP));
 
index 607976c..8b5c619 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * VXLAN: Virtual eXtensiable Local Area Network
+ * VXLAN: Virtual eXtensible Local Area Network
  *
  * Copyright (c) 2012 Vyatta Inc.
  *
@@ -50,8 +50,8 @@
 
 #define VXLAN_N_VID    (1u << 24)
 #define VXLAN_VID_MASK (VXLAN_N_VID - 1)
-/* VLAN + IP header + UDP + VXLAN */
-#define VXLAN_HEADROOM (4 + 20 + 8 + 8)
+/* IP header + UDP + VXLAN + Ethernet header */
+#define VXLAN_HEADROOM (20 + 8 + 8 + 14)
 
 #define VXLAN_FLAGS 0x08000000 /* struct vxlanhdr.vx_flags required value. */
 
@@ -816,7 +816,7 @@ static void vxlan_cleanup(unsigned long arg)
                                = container_of(p, struct vxlan_fdb, hlist);
                        unsigned long timeout;
 
-                       if (f->state == NUD_PERMANENT)
+                       if (f->state & NUD_PERMANENT)
                                continue;
 
                        timeout = f->used + vxlan->age_interval * HZ;
@@ -1102,6 +1102,10 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
 
                if (!tb[IFLA_MTU])
                        dev->mtu = lowerdev->mtu - VXLAN_HEADROOM;
+
+               /* update header length based on lower device */
+               dev->hard_header_len = lowerdev->hard_header_len +
+                                      VXLAN_HEADROOM;
        }
 
        if (data[IFLA_VXLAN_TOS])
index 3f575af..760776b 100644 (file)
@@ -969,10 +969,12 @@ static int init_hdlc_queues(struct port *port)
 {
        int i;
 
-       if (!ports_open)
-               if (!(dma_pool = dma_pool_create(DRV_NAME, NULL,
-                                                POOL_ALLOC_SIZE, 32, 0)))
+       if (!ports_open) {
+               dma_pool = dma_pool_create(DRV_NAME, &port->netdev->dev,
+                                          POOL_ALLOC_SIZE, 32, 0);
+               if (!dma_pool)
                        return -ENOMEM;
+       }
 
        if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL,
                                              &port->desc_tab_phys)))
@@ -1363,7 +1365,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 89bf94d..6f7cf49 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 924c461..f5dda84 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 8e1559a..1829b44 100644 (file)
@@ -1456,7 +1456,7 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
        switch (type) {
        case ATH9K_RESET_POWER_ON:
                ret = ath9k_hw_set_reset_power_on(ah);
-               if (!ret)
+               if (ret)
                        ah->reset_power_on = true;
                break;
        case ATH9K_RESET_WARM:
index 378bd70..741918a 100644 (file)
@@ -312,6 +312,7 @@ static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
        }
 
        bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
+       bf->bf_next = NULL;
        list_del(&bf->list);
 
        spin_unlock_bh(&sc->tx.txbuflock);
@@ -393,7 +394,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
        u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0, seq_first;
        u32 ba[WME_BA_BMP_SIZE >> 5];
        int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
-       bool rc_update = true;
+       bool rc_update = true, isba;
        struct ieee80211_tx_rate rates[4];
        struct ath_frame_info *fi;
        int nframes;
@@ -437,13 +438,17 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
        tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
        tid = ATH_AN_2_TID(an, tidno);
        seq_first = tid->seq_start;
+       isba = ts->ts_flags & ATH9K_TX_BA;
 
        /*
         * The hardware occasionally sends a tx status for the wrong TID.
         * In this case, the BA status cannot be considered valid and all
         * subframes need to be retransmitted
+        *
+        * Only BlockAcks have a TID and therefore normal Acks cannot be
+        * checked
         */
-       if (tidno != ts->tid)
+       if (isba && tidno != ts->tid)
                txok = false;
 
        isaggr = bf_isaggr(bf);
@@ -1774,6 +1779,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
        list_add_tail(&bf->list, &bf_head);
        bf->bf_state.bf_type = 0;
 
+       bf->bf_next = NULL;
        bf->bf_lastbf = bf;
        ath_tx_fill_desc(sc, bf, txq, fi->framelen);
        ath_tx_txqaddbuf(sc, txq, &bf_head, false);
index 73730e9..c5a99c8 100644 (file)
@@ -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 192251a..282eede 100644 (file)
@@ -382,7 +382,7 @@ static void cancel_transfers(struct b43legacy_pioqueue *queue)
 {
        struct b43legacy_pio_txpacket *packet, *tmp_packet;
 
-       tasklet_disable(&queue->txtask);
+       tasklet_kill(&queue->txtask);
 
        list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list)
                free_txpacket(packet, 0);
index a2b4b1e..7a6dfdc 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 c1abaa6..481345c 100644 (file)
@@ -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;
        }
 
@@ -3972,7 +3972,7 @@ 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;
+       int mgmt_ie_buf_len;
        u32 *mgmt_ie_len = 0;
        u32 del_add_ie_buf_len = 0;
        u32 total_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);
@@ -4401,7 +4401,7 @@ static s32 brcmf_mode_to_nl80211_iftype(s32 mode)
 
 static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
 {
-#ifndef CONFIG_BRCMFISCAN
+#ifndef CONFIG_BRCMISCAN
        /* scheduled scan settings */
        wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
        wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
@@ -4606,12 +4606,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 +4620,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 +4645,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 +5200,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 +5418,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 935120f..768bf61 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 349c205..da58620 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 ff8162d..2d9eee9 100644 (file)
@@ -521,7 +521,7 @@ static void iwlagn_mac_tx(struct ieee80211_hw *hw,
                     ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
 
        if (iwlagn_tx_skb(priv, control->sta, skb))
-               dev_kfree_skb_any(skb);
+               ieee80211_free_txskb(hw, skb);
 }
 
 static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
@@ -1354,6 +1354,20 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
        vif_priv->ctx = ctx;
        ctx->vif = vif;
 
+       /*
+        * In SNIFFER device type, the firmware reports the FCS to
+        * the host, rather than snipping it off. Unfortunately,
+        * mac80211 doesn't (yet) provide a per-packet flag for
+        * this, so that we have to set the hardware flag based
+        * on the interfaces added. As the monitor interface can
+        * only be present by itself, and will be removed before
+        * other interfaces are added, this is safe.
+        */
+       if (vif->type == NL80211_IFTYPE_MONITOR)
+               priv->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS;
+       else
+               priv->hw->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
+
        err = iwl_setup_interface(priv, ctx);
        if (!err || reset)
                goto out;
index 7ff3f14..408132c 100644 (file)
@@ -2114,7 +2114,7 @@ static void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
 
        info = IEEE80211_SKB_CB(skb);
        iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]);
-       dev_kfree_skb_any(skb);
+       ieee80211_free_txskb(priv->hw, skb);
 }
 
 static void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
index 1089639..2830ea2 100644 (file)
@@ -1012,12 +1012,12 @@ static void iwl_calc_basic_rates(struct iwl_priv *priv,
         * As a consequence, it's not as complicated as it sounds, just add
         * any lower rates to the ACK rate bitmap.
         */
-       if (IWL_RATE_11M_INDEX < lowest_present_ofdm)
-               ofdm |= IWL_RATE_11M_MASK >> IWL_FIRST_CCK_RATE;
-       if (IWL_RATE_5M_INDEX < lowest_present_ofdm)
-               ofdm |= IWL_RATE_5M_MASK >> IWL_FIRST_CCK_RATE;
-       if (IWL_RATE_2M_INDEX < lowest_present_ofdm)
-               ofdm |= IWL_RATE_2M_MASK >> IWL_FIRST_CCK_RATE;
+       if (IWL_RATE_11M_INDEX < lowest_present_cck)
+               cck |= IWL_RATE_11M_MASK >> IWL_FIRST_CCK_RATE;
+       if (IWL_RATE_5M_INDEX < lowest_present_cck)
+               cck |= IWL_RATE_5M_MASK >> IWL_FIRST_CCK_RATE;
+       if (IWL_RATE_2M_INDEX < lowest_present_cck)
+               cck |= IWL_RATE_2M_MASK >> IWL_FIRST_CCK_RATE;
        /* 1M already there or needed so always add */
        cck |= IWL_RATE_1M_MASK >> IWL_FIRST_CCK_RATE;
 
index 17c8e5d..bb69f8f 100644 (file)
@@ -321,6 +321,14 @@ static void iwl_rx_allocate(struct iwl_trans *trans, gfp_t priority)
                        dma_map_page(trans->dev, page, 0,
                                     PAGE_SIZE << trans_pcie->rx_page_order,
                                     DMA_FROM_DEVICE);
+               if (dma_mapping_error(trans->dev, rxb->page_dma)) {
+                       rxb->page = NULL;
+                       spin_lock_irqsave(&rxq->lock, flags);
+                       list_add(&rxb->list, &rxq->rx_used);
+                       spin_unlock_irqrestore(&rxq->lock, flags);
+                       __free_pages(page, trans_pcie->rx_page_order);
+                       return;
+               }
                /* dma address must be no more than 36 bits */
                BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
                /* and also 256 byte aligned! */
@@ -488,8 +496,19 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
                        dma_map_page(trans->dev, rxb->page, 0,
                                     PAGE_SIZE << trans_pcie->rx_page_order,
                                     DMA_FROM_DEVICE);
-               list_add_tail(&rxb->list, &rxq->rx_free);
-               rxq->free_count++;
+               if (dma_mapping_error(trans->dev, rxb->page_dma)) {
+                       /*
+                        * free the page(s) as well to not break
+                        * the invariant that the items on the used
+                        * list have no page(s)
+                        */
+                       __free_pages(rxb->page, trans_pcie->rx_page_order);
+                       rxb->page = NULL;
+                       list_add_tail(&rxb->list, &rxq->rx_used);
+               } else {
+                       list_add_tail(&rxb->list, &rxq->rx_free);
+                       rxq->free_count++;
+               }
        } else
                list_add_tail(&rxb->list, &rxq->rx_used);
        spin_unlock_irqrestore(&rxq->lock, flags);
index 105e3af..79a4ddc 100644 (file)
@@ -480,20 +480,12 @@ 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;
 
        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));
-
-       WARN_ONCE(rd_ptr != wr_ptr, "queue %d isn't empty: [%d,%d]",
-                 txq_id, rd_ptr, wr_ptr);
-
        iwl_txq_set_inactive(trans, txq_id);
        IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id);
 }
index 0679458..780d3e1 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;
        }
 
index 8d46510..ae9010e 100644 (file)
@@ -890,9 +890,6 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
                return;
        }
        cmd_node = adapter->curr_cmd;
-       if (cmd_node->wait_q_enabled)
-               adapter->cmd_wait_q.status = -ETIMEDOUT;
-
        if (cmd_node) {
                adapter->dbg.timeout_cmd_id =
                        adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index];
@@ -938,6 +935,14 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
 
                dev_err(adapter->dev, "ps_mode=%d ps_state=%d\n",
                        adapter->ps_mode, adapter->ps_state);
+
+               if (cmd_node->wait_q_enabled) {
+                       adapter->cmd_wait_q.status = -ETIMEDOUT;
+                       wake_up_interruptible(&adapter->cmd_wait_q.wait);
+                       mwifiex_cancel_pending_ioctl(adapter);
+                       /* reset cmd_sent flag to unblock new commands */
+                       adapter->cmd_sent = false;
+               }
        }
        if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING)
                mwifiex_init_fw_complete(adapter);
index 00b658d..9171aae 100644 (file)
@@ -1843,21 +1843,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 fc8a9bf..82cf0fa 100644 (file)
@@ -161,7 +161,6 @@ static int mwifiex_sdio_suspend(struct device *dev)
        struct sdio_mmc_card *card;
        struct mwifiex_adapter *adapter;
        mmc_pm_flag_t pm_flag = 0;
-       int hs_actived = 0;
        int i;
        int ret = 0;
 
@@ -188,12 +187,14 @@ static int mwifiex_sdio_suspend(struct device *dev)
        adapter = card->adapter;
 
        /* Enable the Host Sleep */
-       hs_actived = mwifiex_enable_hs(adapter);
-       if (hs_actived) {
-               pr_debug("cmd: suspend with MMC_PM_KEEP_POWER\n");
-               ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+       if (!mwifiex_enable_hs(adapter)) {
+               dev_err(adapter->dev, "cmd: failed to suspend\n");
+               return -EFAULT;
        }
 
+       dev_dbg(adapter->dev, "cmd: suspend with MMC_PM_KEEP_POWER\n");
+       ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+
        /* Indicate device suspended */
        adapter->is_suspended = true;
 
index a12e84f..6b2e1e4 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 01dc889..59474ae 100644 (file)
@@ -2449,7 +2449,7 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev)
        /*
         * Check if temperature compensation is supported.
         */
-       if (tssi_bounds[4] == 0xff)
+       if (tssi_bounds[4] == 0xff || step == 0xff)
                return 0;
 
        /*
index c9e9370..3b8fb5a 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 e5eb43b..24eec66 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 9970c2b..b7e6607 100644 (file)
@@ -297,6 +297,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
        /*=== Customer ID ===*/
        /****** 8188CU ********/
        {RTL_USB_DEVICE(0x050d, 0x1102, rtl92cu_hal_cfg)}, /*Belkin - Edimax*/
+       {RTL_USB_DEVICE(0x050d, 0x11f2, rtl92cu_hal_cfg)}, /*Belkin - ISY*/
        {RTL_USB_DEVICE(0x06f8, 0xe033, rtl92cu_hal_cfg)}, /*Hercules - Edimax*/
        {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/
        {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/
index 030beb4..e3ea4b3 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 caa0110..fc24eb9 100644 (file)
@@ -452,29 +452,85 @@ static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev,
        /* Grant backend access to each skb fragment page. */
        for (i = 0; i < frags; i++) {
                skb_frag_t *frag = skb_shinfo(skb)->frags + i;
+               struct page *page = skb_frag_page(frag);
 
-               tx->flags |= XEN_NETTXF_more_data;
+               len = skb_frag_size(frag);
+               offset = frag->page_offset;
 
-               id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs);
-               np->tx_skbs[id].skb = skb_get(skb);
-               tx = RING_GET_REQUEST(&np->tx, prod++);
-               tx->id = id;
-               ref = gnttab_claim_grant_reference(&np->gref_tx_head);
-               BUG_ON((signed short)ref < 0);
+               /* Data must not cross a page boundary. */
+               BUG_ON(len + offset > PAGE_SIZE<<compound_order(page));
 
-               mfn = pfn_to_mfn(page_to_pfn(skb_frag_page(frag)));
-               gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id,
-                                               mfn, GNTMAP_readonly);
+               /* Skip unused frames from start of page */
+               page += offset >> PAGE_SHIFT;
+               offset &= ~PAGE_MASK;
 
-               tx->gref = np->grant_tx_ref[id] = ref;
-               tx->offset = frag->page_offset;
-               tx->size = skb_frag_size(frag);
-               tx->flags = 0;
+               while (len > 0) {
+                       unsigned long bytes;
+
+                       BUG_ON(offset >= PAGE_SIZE);
+
+                       bytes = PAGE_SIZE - offset;
+                       if (bytes > len)
+                               bytes = len;
+
+                       tx->flags |= XEN_NETTXF_more_data;
+
+                       id = get_id_from_freelist(&np->tx_skb_freelist,
+                                                 np->tx_skbs);
+                       np->tx_skbs[id].skb = skb_get(skb);
+                       tx = RING_GET_REQUEST(&np->tx, prod++);
+                       tx->id = id;
+                       ref = gnttab_claim_grant_reference(&np->gref_tx_head);
+                       BUG_ON((signed short)ref < 0);
+
+                       mfn = pfn_to_mfn(page_to_pfn(page));
+                       gnttab_grant_foreign_access_ref(ref,
+                                                       np->xbdev->otherend_id,
+                                                       mfn, GNTMAP_readonly);
+
+                       tx->gref = np->grant_tx_ref[id] = ref;
+                       tx->offset = offset;
+                       tx->size = bytes;
+                       tx->flags = 0;
+
+                       offset += bytes;
+                       len -= bytes;
+
+                       /* Next frame */
+                       if (offset == PAGE_SIZE && len) {
+                               BUG_ON(!PageCompound(page));
+                               page++;
+                               offset = 0;
+                       }
+               }
        }
 
        np->tx.req_prod_pvt = prod;
 }
 
+/*
+ * Count how many ring slots are required to send the frags of this
+ * skb. Each frag might be a compound page.
+ */
+static int xennet_count_skb_frag_slots(struct sk_buff *skb)
+{
+       int i, frags = skb_shinfo(skb)->nr_frags;
+       int pages = 0;
+
+       for (i = 0; i < frags; i++) {
+               skb_frag_t *frag = skb_shinfo(skb)->frags + i;
+               unsigned long size = skb_frag_size(frag);
+               unsigned long offset = frag->page_offset;
+
+               /* Skip unused frames from start of page */
+               offset &= ~PAGE_MASK;
+
+               pages += PFN_UP(offset + size);
+       }
+
+       return pages;
+}
+
 static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        unsigned short id;
@@ -487,23 +543,23 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
        grant_ref_t ref;
        unsigned long mfn;
        int notify;
-       int frags = skb_shinfo(skb)->nr_frags;
+       int slots;
        unsigned int offset = offset_in_page(data);
        unsigned int len = skb_headlen(skb);
        unsigned long flags;
 
-       frags += DIV_ROUND_UP(offset + len, PAGE_SIZE);
-       if (unlikely(frags > MAX_SKB_FRAGS + 1)) {
-               printk(KERN_ALERT "xennet: skb rides the rocket: %d frags\n",
-                      frags);
-               dump_stack();
+       slots = DIV_ROUND_UP(offset + len, PAGE_SIZE) +
+               xennet_count_skb_frag_slots(skb);
+       if (unlikely(slots > MAX_SKB_FRAGS + 1)) {
+               net_alert_ratelimited(
+                       "xennet: skb rides the rocket: %d slots\n", slots);
                goto drop;
        }
 
        spin_lock_irqsave(&np->tx_lock, flags);
 
        if (unlikely(!netif_carrier_ok(dev) ||
-                    (frags > 1 && !xennet_can_sg(dev)) ||
+                    (slots > 1 && !xennet_can_sg(dev)) ||
                     netif_needs_gso(skb, netif_skb_features(skb)))) {
                spin_unlock_irqrestore(&np->tx_lock, flags);
                goto drop;
index 97c440a..30ae18a 100644 (file)
@@ -698,13 +698,14 @@ static void pn533_wq_cmd(struct work_struct *work)
 
        cmd = list_first_entry(&dev->cmd_queue, struct pn533_cmd, queue);
 
+       list_del(&cmd->queue);
+
        mutex_unlock(&dev->cmd_lock);
 
        __pn533_send_cmd_frame_async(dev, cmd->out_frame, cmd->in_frame,
                                     cmd->in_frame_len, cmd->cmd_complete,
                                     cmd->arg, cmd->flags);
 
-       list_del(&cmd->queue);
        kfree(cmd);
 }
 
@@ -1678,11 +1679,14 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev,
 static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
                                                u8 *params, int params_len)
 {
-       struct pn533_cmd_jump_dep *cmd;
        struct pn533_cmd_jump_dep_response *resp;
        struct nfc_target nfc_target;
        u8 target_gt_len;
        int rc;
+       struct pn533_cmd_jump_dep *cmd = (struct pn533_cmd_jump_dep *)arg;
+       u8 active = cmd->active;
+
+       kfree(arg);
 
        if (params_len == -ENOENT) {
                nfc_dev_dbg(&dev->interface->dev, "");
@@ -1704,7 +1708,6 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
        }
 
        resp = (struct pn533_cmd_jump_dep_response *) params;
-       cmd = (struct pn533_cmd_jump_dep *) arg;
        rc = resp->status & PN533_CMD_RET_MASK;
        if (rc != PN533_CMD_RET_SUCCESS) {
                nfc_dev_err(&dev->interface->dev,
@@ -1734,7 +1737,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
        if (rc == 0)
                rc = nfc_dep_link_is_up(dev->nfc_dev,
                                                dev->nfc_dev->targets[0].idx,
-                                               !cmd->active, NFC_RF_INITIATOR);
+                                               !active, NFC_RF_INITIATOR);
 
        return 0;
 }
@@ -1819,12 +1822,8 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
        rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame,
                                dev->in_maxlen, pn533_in_dep_link_up_complete,
                                cmd, GFP_KERNEL);
-       if (rc)
-               goto out;
-
-
-out:
-       kfree(cmd);
+       if (rc < 0)
+               kfree(cmd);
 
        return rc;
 }
@@ -2078,8 +2077,12 @@ error:
 static int pn533_tm_send_complete(struct pn533 *dev, void *arg,
                                  u8 *params, int params_len)
 {
+       struct sk_buff *skb_out = arg;
+
        nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
 
+       dev_kfree_skb(skb_out);
+
        if (params_len < 0) {
                nfc_dev_err(&dev->interface->dev,
                            "Error %d when sending data",
@@ -2117,7 +2120,7 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb)
 
        rc = pn533_send_cmd_frame_async(dev, out_frame, dev->in_frame,
                                        dev->in_maxlen, pn533_tm_send_complete,
-                                       NULL, GFP_KERNEL);
+                                       skb, GFP_KERNEL);
        if (rc) {
                nfc_dev_err(&dev->interface->dev,
                            "Error %d when trying to send data", rc);
index 72e496f..0125524 100644 (file)
@@ -37,9 +37,9 @@ struct of_bus {
        int             (*match)(struct device_node *parent);
        void            (*count_cells)(struct device_node *child,
                                       int *addrc, int *sizec);
-       u64             (*map)(u32 *addr, const __be32 *range,
+       u64             (*map)(__be32 *addr, const __be32 *range,
                                int na, int ns, int pna);
-       int             (*translate)(u32 *addr, u64 offset, int na);
+       int             (*translate)(__be32 *addr, u64 offset, int na);
        unsigned int    (*get_flags)(const __be32 *addr);
 };
 
@@ -56,7 +56,7 @@ static void of_bus_default_count_cells(struct device_node *dev,
                *sizec = of_n_size_cells(dev);
 }
 
-static u64 of_bus_default_map(u32 *addr, const __be32 *range,
+static u64 of_bus_default_map(__be32 *addr, const __be32 *range,
                int na, int ns, int pna)
 {
        u64 cp, s, da;
@@ -82,7 +82,7 @@ static u64 of_bus_default_map(u32 *addr, const __be32 *range,
        return da - cp;
 }
 
-static int of_bus_default_translate(u32 *addr, u64 offset, int na)
+static int of_bus_default_translate(__be32 *addr, u64 offset, int na)
 {
        u64 a = of_read_number(addr, na);
        memset(addr, 0, na * 4);
@@ -138,7 +138,7 @@ static unsigned int of_bus_pci_get_flags(const __be32 *addr)
        return flags;
 }
 
-static u64 of_bus_pci_map(u32 *addr, const __be32 *range, int na, int ns,
+static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns,
                int pna)
 {
        u64 cp, s, da;
@@ -165,7 +165,7 @@ static u64 of_bus_pci_map(u32 *addr, const __be32 *range, int na, int ns,
        return da - cp;
 }
 
-static int of_bus_pci_translate(u32 *addr, u64 offset, int na)
+static int of_bus_pci_translate(__be32 *addr, u64 offset, int na)
 {
        return of_bus_default_translate(addr + 1, offset, na - 1);
 }
@@ -247,7 +247,7 @@ static void of_bus_isa_count_cells(struct device_node *child,
                *sizec = 1;
 }
 
-static u64 of_bus_isa_map(u32 *addr, const __be32 *range, int na, int ns,
+static u64 of_bus_isa_map(__be32 *addr, const __be32 *range, int na, int ns,
                int pna)
 {
        u64 cp, s, da;
@@ -270,7 +270,7 @@ static u64 of_bus_isa_map(u32 *addr, const __be32 *range, int na, int ns,
        return da - cp;
 }
 
-static int of_bus_isa_translate(u32 *addr, u64 offset, int na)
+static int of_bus_isa_translate(__be32 *addr, u64 offset, int na)
 {
        return of_bus_default_translate(addr + 1, offset, na - 1);
 }
@@ -338,7 +338,7 @@ static struct of_bus *of_match_bus(struct device_node *np)
 }
 
 static int of_translate_one(struct device_node *parent, struct of_bus *bus,
-                           struct of_bus *pbus, u32 *addr,
+                           struct of_bus *pbus, __be32 *addr,
                            int na, int ns, int pna, const char *rprop)
 {
        const __be32 *ranges;
@@ -409,12 +409,12 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
  * that can be mapped to a cpu physical address). This is not really specified
  * that way, but this is traditionally the way IBM at least do things
  */
-u64 __of_translate_address(struct device_node *dev, const __be32 *in_addr,
-                          const char *rprop)
+static u64 __of_translate_address(struct device_node *dev,
+                                 const __be32 *in_addr, const char *rprop)
 {
        struct device_node *parent = NULL;
        struct of_bus *bus, *pbus;
-       u32 addr[OF_MAX_ADDR_CELLS];
+       __be32 addr[OF_MAX_ADDR_CELLS];
        int na, ns, pna, pns;
        u64 result = OF_BAD_ADDR;
 
index af3b22a..538e3cf 100644 (file)
@@ -45,7 +45,8 @@ struct alias_prop {
 
 static LIST_HEAD(aliases_lookup);
 
-struct device_node *allnodes;
+struct device_node *of_allnodes;
+EXPORT_SYMBOL(of_allnodes);
 struct device_node *of_chosen;
 struct device_node *of_aliases;
 
@@ -199,7 +200,7 @@ struct device_node *of_find_all_nodes(struct device_node *prev)
        struct device_node *np;
 
        read_lock(&devtree_lock);
-       np = prev ? prev->allnext : allnodes;
+       np = prev ? prev->allnext : of_allnodes;
        for (; np != NULL; np = np->allnext)
                if (of_node_get(np))
                        break;
@@ -422,7 +423,7 @@ EXPORT_SYMBOL(of_get_child_by_name);
  */
 struct device_node *of_find_node_by_path(const char *path)
 {
-       struct device_node *np = allnodes;
+       struct device_node *np = of_allnodes;
 
        read_lock(&devtree_lock);
        for (; np; np = np->allnext) {
@@ -452,7 +453,7 @@ struct device_node *of_find_node_by_name(struct device_node *from,
        struct device_node *np;
 
        read_lock(&devtree_lock);
-       np = from ? from->allnext : allnodes;
+       np = from ? from->allnext : of_allnodes;
        for (; np; np = np->allnext)
                if (np->name && (of_node_cmp(np->name, name) == 0)
                    && of_node_get(np))
@@ -481,7 +482,7 @@ struct device_node *of_find_node_by_type(struct device_node *from,
        struct device_node *np;
 
        read_lock(&devtree_lock);
-       np = from ? from->allnext : allnodes;
+       np = from ? from->allnext : of_allnodes;
        for (; np; np = np->allnext)
                if (np->type && (of_node_cmp(np->type, type) == 0)
                    && of_node_get(np))
@@ -512,7 +513,7 @@ struct device_node *of_find_compatible_node(struct device_node *from,
        struct device_node *np;
 
        read_lock(&devtree_lock);
-       np = from ? from->allnext : allnodes;
+       np = from ? from->allnext : of_allnodes;
        for (; np; np = np->allnext) {
                if (type
                    && !(np->type && (of_node_cmp(np->type, type) == 0)))
@@ -545,7 +546,7 @@ struct device_node *of_find_node_with_property(struct device_node *from,
        struct property *pp;
 
        read_lock(&devtree_lock);
-       np = from ? from->allnext : allnodes;
+       np = from ? from->allnext : of_allnodes;
        for (; np; np = np->allnext) {
                for (pp = np->properties; pp; pp = pp->next) {
                        if (of_prop_cmp(pp->name, prop_name) == 0) {
@@ -594,27 +595,35 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches,
 EXPORT_SYMBOL(of_match_node);
 
 /**
- *     of_find_matching_node - Find a node based on an of_device_id match
- *                             table.
+ *     of_find_matching_node_and_match - Find a node based on an of_device_id
+ *                                       match table.
  *     @from:          The node to start searching from or NULL, the node
  *                     you pass will not be searched, only the next one
  *                     will; typically, you pass what the previous call
  *                     returned. of_node_put() will be called on it
  *     @matches:       array of of device match structures to search in
+ *     @match          Updated to point at the matches entry which matched
  *
  *     Returns a node pointer with refcount incremented, use
  *     of_node_put() on it when done.
  */
-struct device_node *of_find_matching_node(struct device_node *from,
-                                         const struct of_device_id *matches)
+struct device_node *of_find_matching_node_and_match(struct device_node *from,
+                                       const struct of_device_id *matches,
+                                       const struct of_device_id **match)
 {
        struct device_node *np;
 
+       if (match)
+               *match = NULL;
+
        read_lock(&devtree_lock);
-       np = from ? from->allnext : allnodes;
+       np = from ? from->allnext : of_allnodes;
        for (; np; np = np->allnext) {
-               if (of_match_node(matches, np) && of_node_get(np))
+               if (of_match_node(matches, np) && of_node_get(np)) {
+                       if (match)
+                               *match = matches;
                        break;
+               }
        }
        of_node_put(from);
        read_unlock(&devtree_lock);
@@ -661,7 +670,7 @@ struct device_node *of_find_node_by_phandle(phandle handle)
        struct device_node *np;
 
        read_lock(&devtree_lock);
-       for (np = allnodes; np; np = np->allnext)
+       for (np = of_allnodes; np; np = np->allnext)
                if (np->phandle == handle)
                        break;
        of_node_get(np);
@@ -671,12 +680,89 @@ struct device_node *of_find_node_by_phandle(phandle handle)
 EXPORT_SYMBOL(of_find_node_by_phandle);
 
 /**
+ * of_property_read_u8_array - Find and read an array of u8 from a property.
+ *
+ * @np:                device node from which the property value is to be read.
+ * @propname:  name of the property to be searched.
+ * @out_value: pointer to return value, modified only if return value is 0.
+ * @sz:                number of array elements to read
+ *
+ * Search for a property in a device node and read 8-bit value(s) from
+ * it. Returns 0 on success, -EINVAL if the property does not exist,
+ * -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data isn't large enough.
+ *
+ * dts entry of array should be like:
+ *     property = /bits/ 8 <0x50 0x60 0x70>;
+ *
+ * The out_value is modified only if a valid u8 value can be decoded.
+ */
+int of_property_read_u8_array(const struct device_node *np,
+                       const char *propname, u8 *out_values, size_t sz)
+{
+       struct property *prop = of_find_property(np, propname, NULL);
+       const u8 *val;
+
+       if (!prop)
+               return -EINVAL;
+       if (!prop->value)
+               return -ENODATA;
+       if ((sz * sizeof(*out_values)) > prop->length)
+               return -EOVERFLOW;
+
+       val = prop->value;
+       while (sz--)
+               *out_values++ = *val++;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(of_property_read_u8_array);
+
+/**
+ * of_property_read_u16_array - Find and read an array of u16 from a property.
+ *
+ * @np:                device node from which the property value is to be read.
+ * @propname:  name of the property to be searched.
+ * @out_value: pointer to return value, modified only if return value is 0.
+ * @sz:                number of array elements to read
+ *
+ * Search for a property in a device node and read 16-bit value(s) from
+ * it. Returns 0 on success, -EINVAL if the property does not exist,
+ * -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data isn't large enough.
+ *
+ * dts entry of array should be like:
+ *     property = /bits/ 16 <0x5000 0x6000 0x7000>;
+ *
+ * The out_value is modified only if a valid u16 value can be decoded.
+ */
+int of_property_read_u16_array(const struct device_node *np,
+                       const char *propname, u16 *out_values, size_t sz)
+{
+       struct property *prop = of_find_property(np, propname, NULL);
+       const __be16 *val;
+
+       if (!prop)
+               return -EINVAL;
+       if (!prop->value)
+               return -ENODATA;
+       if ((sz * sizeof(*out_values)) > prop->length)
+               return -EOVERFLOW;
+
+       val = prop->value;
+       while (sz--)
+               *out_values++ = be16_to_cpup(val++);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(of_property_read_u16_array);
+
+/**
  * of_property_read_u32_array - Find and read an array of 32 bit integers
  * from a property.
  *
  * @np:                device node from which the property value is to be read.
  * @propname:  name of the property to be searched.
  * @out_value: pointer to return value, modified only if return value is 0.
+ * @sz:                number of array elements to read
  *
  * Search for a property in a device node and read 32-bit value(s) from
  * it. Returns 0 on success, -EINVAL if the property does not exist,
@@ -893,8 +979,8 @@ EXPORT_SYMBOL_GPL(of_property_count_strings);
  * Returns the device_node pointer with refcount incremented.  Use
  * of_node_put() on it when done.
  */
-struct device_node *
-of_parse_phandle(struct device_node *np, const char *phandle_name, int index)
+struct device_node *of_parse_phandle(const struct device_node *np,
+                                    const char *phandle_name, int index)
 {
        const __be32 *phandle;
        int size;
@@ -1169,9 +1255,9 @@ void of_attach_node(struct device_node *np)
 
        write_lock_irqsave(&devtree_lock, flags);
        np->sibling = np->parent->child;
-       np->allnext = allnodes;
+       np->allnext = of_allnodes;
        np->parent->child = np;
-       allnodes = np;
+       of_allnodes = np;
        write_unlock_irqrestore(&devtree_lock, flags);
 }
 
@@ -1192,11 +1278,11 @@ void of_detach_node(struct device_node *np)
        if (!parent)
                goto out_unlock;
 
-       if (allnodes == np)
-               allnodes = np->allnext;
+       if (of_allnodes == np)
+               of_allnodes = np->allnext;
        else {
                struct device_node *prev;
-               for (prev = allnodes;
+               for (prev = of_allnodes;
                     prev->allnext != np;
                     prev = prev->allnext)
                        ;
index 91a375f..a65c39c 100644 (file)
@@ -186,6 +186,8 @@ static unsigned long unflatten_dt_node(struct boot_param_header *blob,
                         */
                        fpsize = 1;
                        allocl = 2;
+                       l = 1;
+                       *pathp = '\0';
                } else {
                        /* account for '/' and path size minus terminal 0
                         * already in 'l'
@@ -198,10 +200,10 @@ static unsigned long unflatten_dt_node(struct boot_param_header *blob,
        np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
                                __alignof__(struct device_node));
        if (allnextpp) {
+               char *fn;
                memset(np, 0, sizeof(*np));
-               np->full_name = ((char *)np) + sizeof(struct device_node);
+               np->full_name = fn = ((char *)np) + sizeof(*np);
                if (new_format) {
-                       char *fn = np->full_name;
                        /* rebuild full path for new format */
                        if (dad && dad->parent) {
                                strcpy(fn, dad->full_name);
@@ -215,9 +217,9 @@ static unsigned long unflatten_dt_node(struct boot_param_header *blob,
                                fn += strlen(fn);
                        }
                        *(fn++) = '/';
-                       memcpy(fn, pathp, l);
-               } else
-                       memcpy(np->full_name, pathp, l);
+               }
+               memcpy(fn, pathp, l);
+
                prev_pp = &np->properties;
                **allnextpp = np;
                *allnextpp = &np->allnext;
@@ -459,7 +461,7 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node,
 
        do {
                u32 tag = be32_to_cpup((__be32 *)p);
-               char *pathp;
+               const char *pathp;
 
                p += 4;
                if (tag == OF_DT_END_NODE) {
@@ -487,7 +489,7 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node,
                pathp = (char *)p;
                p = ALIGN(p + strlen(pathp) + 1, 4);
                if ((*pathp) == '/') {
-                       char *lp, *np;
+                       const char *lp, *np;
                        for (lp = NULL, np = pathp; *np; np++)
                                if ((*np) == '/')
                                        lp = np+1;
@@ -710,7 +712,7 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
  */
 void __init unflatten_device_tree(void)
 {
-       __unflatten_device_tree(initial_boot_params, &allnodes,
+       __unflatten_device_tree(initial_boot_params, &of_allnodes,
                                early_init_dt_alloc_memory_arch);
 
        /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
index a23ec77..a3c1c5a 100644 (file)
@@ -192,11 +192,13 @@ int of_irq_map_raw(struct device_node *parent, const __be32 *intspec,
                        /* Compare specifiers */
                        match = 1;
                        for (i = 0; i < addrsize && match; ++i) {
-                               u32 mask = imask ? imask[i] : 0xffffffffu;
+                               __be32 mask = imask ? imask[i]
+                                                   : cpu_to_be32(0xffffffffu);
                                match = ((addr[i] ^ imap[i]) & mask) == 0;
                        }
                        for (; i < (addrsize + intsize) && match; ++i) {
-                               u32 mask = imask ? imask[i] : 0xffffffffu;
+                               __be32 mask = imask ? imask[i]
+                                                   : cpu_to_be32(0xffffffffu);
                                match =
                                   ((intspec[i-addrsize] ^ imap[i]) & mask) == 0;
                        }
@@ -465,7 +467,7 @@ void __init of_irq_init(const struct of_device_id *matches)
                        pr_debug("of_irq_init: init %s @ %p, parent %p\n",
                                 match->compatible,
                                 desc->dev, desc->interrupt_parent);
-                       irq_init_cb = match->data;
+                       irq_init_cb = (of_irq_init_cb_t)match->data;
                        ret = irq_init_cb(desc->dev, desc->interrupt_parent);
                        if (ret) {
                                kfree(desc);
index 3550f3b..b667264 100644 (file)
@@ -29,7 +29,7 @@ void of_i2c_register_devices(struct i2c_adapter *adap)
 
        dev_dbg(&adap->dev, "of_i2c: walking child nodes\n");
 
-       for_each_child_of_node(adap->dev.of_node, node) {
+       for_each_available_child_of_node(adap->dev.of_node, node) {
                struct i2c_board_info info = {};
                struct dev_archdata dev_ad = {};
                const __be32 *addr;
index 8e6c25f..83ca06f 100644 (file)
@@ -53,7 +53,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
                return rc;
 
        /* Loop over the child nodes and register a phy_device for each one */
-       for_each_child_of_node(np, child) {
+       for_each_available_child_of_node(np, child) {
                const __be32 *paddr;
                u32 addr;
                int len;
index 07cc1d6..37b56fd 100644 (file)
@@ -241,15 +241,15 @@ void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops)
        BUG_ON(!ops);
        of_pdt_prom_ops = ops;
 
-       allnodes = of_pdt_create_node(root_node, NULL);
+       of_allnodes = of_pdt_create_node(root_node, NULL);
 #if defined(CONFIG_SPARC)
-       allnodes->path_component_name = "";
+       of_allnodes->path_component_name = "";
 #endif
-       allnodes->full_name = "/";
+       of_allnodes->full_name = "/";
 
-       nextp = &allnodes->allnext;
-       allnodes->child = of_pdt_build_tree(allnodes,
-                       of_pdt_prom_ops->getchild(allnodes->phandle), &nextp);
+       nextp = &of_allnodes->allnext;
+       of_allnodes->child = of_pdt_build_tree(of_allnodes,
+                       of_pdt_prom_ops->getchild(of_allnodes->phandle), &nextp);
 
        /* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
        of_alias_scan(kernel_tree_alloc);
index 9bdeaf3..b80891b 100644 (file)
@@ -76,7 +76,7 @@ void of_device_make_bus_id(struct device *dev)
 {
        static atomic_t bus_no_reg_magic;
        struct device_node *node = dev->of_node;
-       const u32 *reg;
+       const __be32 *reg;
        u64 addr;
        const __be32 *addrp;
        int magic;
index 6241fd0..a543746 100644 (file)
@@ -320,10 +320,7 @@ void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),
                } else
                        next = dev->bus_list.next;
 
-               /* Run device routines with the device locked */
-               device_lock(&dev->dev);
                retval = cb(dev, userdata);
-               device_unlock(&dev->dev);
                if (retval)
                        break;
        }
index c5792d6..1af4008 100644 (file)
 
 #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);
-
 /**
  * pci_acpi_wake_bus - Wake-up notification handler for root buses.
  * @handle: ACPI handle of a device the notification is for.
@@ -68,67 +67,6 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
 }
 
 /**
- * add_pm_notifier - Register PM notifier for given ACPI device.
- * @dev: ACPI device to add the notifier for.
- * @context: PCI device or bus to check for PME status if an event is signaled.
- *
- * NOTE: @dev need not be a run-wake or wake-up device to be a valid source of
- * PM wake-up events.  For example, wake-up events may be generated for bridges
- * if one of the devices below the bridge is signaling PME, even if the bridge
- * itself doesn't have a wake-up GPE associated with it.
- */
-static acpi_status add_pm_notifier(struct acpi_device *dev,
-                                  acpi_notify_handler handler,
-                                  void *context)
-{
-       acpi_status status = AE_ALREADY_EXISTS;
-
-       mutex_lock(&pci_acpi_pm_notify_mtx);
-
-       if (dev->wakeup.flags.notifier_present)
-               goto out;
-
-       status = acpi_install_notify_handler(dev->handle,
-                                            ACPI_SYSTEM_NOTIFY,
-                                            handler, context);
-       if (ACPI_FAILURE(status))
-               goto out;
-
-       dev->wakeup.flags.notifier_present = true;
-
- out:
-       mutex_unlock(&pci_acpi_pm_notify_mtx);
-       return status;
-}
-
-/**
- * remove_pm_notifier - Unregister PM notifier from given ACPI device.
- * @dev: ACPI device to remove the notifier from.
- */
-static acpi_status remove_pm_notifier(struct acpi_device *dev,
-                                     acpi_notify_handler handler)
-{
-       acpi_status status = AE_BAD_PARAMETER;
-
-       mutex_lock(&pci_acpi_pm_notify_mtx);
-
-       if (!dev->wakeup.flags.notifier_present)
-               goto out;
-
-       status = acpi_remove_notify_handler(dev->handle,
-                                           ACPI_SYSTEM_NOTIFY,
-                                           handler);
-       if (ACPI_FAILURE(status))
-               goto out;
-
-       dev->wakeup.flags.notifier_present = false;
-
- out:
-       mutex_unlock(&pci_acpi_pm_notify_mtx);
-       return status;
-}
-
-/**
  * pci_acpi_add_bus_pm_notifier - Register PM notifier for given PCI bus.
  * @dev: ACPI device to add the notifier for.
  * @pci_bus: PCI bus to walk checking for PME status if an event is signaled.
@@ -136,7 +74,7 @@ static acpi_status remove_pm_notifier(struct acpi_device *dev,
 acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev,
                                         struct pci_bus *pci_bus)
 {
-       return add_pm_notifier(dev, pci_acpi_wake_bus, pci_bus);
+       return acpi_add_pm_notifier(dev, pci_acpi_wake_bus, pci_bus);
 }
 
 /**
@@ -145,7 +83,7 @@ acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev,
  */
 acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev)
 {
-       return remove_pm_notifier(dev, pci_acpi_wake_bus);
+       return acpi_remove_pm_notifier(dev, pci_acpi_wake_bus);
 }
 
 /**
@@ -156,7 +94,7 @@ acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev)
 acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev,
                                     struct pci_dev *pci_dev)
 {
-       return add_pm_notifier(dev, pci_acpi_wake_dev, pci_dev);
+       return acpi_add_pm_notifier(dev, pci_acpi_wake_dev, pci_dev);
 }
 
 /**
@@ -165,7 +103,7 @@ acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev,
  */
 acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
 {
-       return remove_pm_notifier(dev, pci_acpi_wake_dev);
+       return acpi_remove_pm_notifier(dev, pci_acpi_wake_dev);
 }
 
 phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle)
@@ -257,11 +195,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 94c6e2a..6c94fc9 100644 (file)
@@ -398,6 +398,8 @@ static void pci_device_shutdown(struct device *dev)
        struct pci_dev *pci_dev = to_pci_dev(dev);
        struct pci_driver *drv = pci_dev->driver;
 
+       pm_runtime_resume(dev);
+
        if (drv && drv->shutdown)
                drv->shutdown(pci_dev);
        pci_msi_shutdown(pci_dev);
@@ -408,16 +410,6 @@ static void pci_device_shutdown(struct device *dev)
         * continue to do DMA
         */
        pci_disable_device(pci_dev);
-
-       /*
-        * Devices may be enabled to wake up by runtime PM, but they need not
-        * be supposed to wake up the system from its "power off" state (e.g.
-        * ACPI S5).  Therefore disable wakeup for all devices that aren't
-        * supposed to wake up the system at this point.  The state argument
-        * will be ignored by pci_enable_wake().
-        */
-       if (!device_may_wakeup(dev))
-               pci_enable_wake(pci_dev, PCI_UNKNOWN, false);
 }
 
 #ifdef CONFIG_PM
index 02d107b..f39378d 100644 (file)
@@ -458,40 +458,6 @@ boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf)
 }
 struct device_attribute vga_attr = __ATTR_RO(boot_vga);
 
-static void
-pci_config_pm_runtime_get(struct pci_dev *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct device *parent = dev->parent;
-
-       if (parent)
-               pm_runtime_get_sync(parent);
-       pm_runtime_get_noresume(dev);
-       /*
-        * pdev->current_state is set to PCI_D3cold during suspending,
-        * so wait until suspending completes
-        */
-       pm_runtime_barrier(dev);
-       /*
-        * Only need to resume devices in D3cold, because config
-        * registers are still accessible for devices suspended but
-        * not in D3cold.
-        */
-       if (pdev->current_state == PCI_D3cold)
-               pm_runtime_resume(dev);
-}
-
-static void
-pci_config_pm_runtime_put(struct pci_dev *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct device *parent = dev->parent;
-
-       pm_runtime_put(dev);
-       if (parent)
-               pm_runtime_put_sync(parent);
-}
-
 static ssize_t
 pci_read_config(struct file *filp, struct kobject *kobj,
                struct bin_attribute *bin_attr,
index 5485883..aabf647 100644 (file)
@@ -1858,6 +1858,38 @@ bool pci_dev_run_wake(struct pci_dev *dev)
 }
 EXPORT_SYMBOL_GPL(pci_dev_run_wake);
 
+void pci_config_pm_runtime_get(struct pci_dev *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device *parent = dev->parent;
+
+       if (parent)
+               pm_runtime_get_sync(parent);
+       pm_runtime_get_noresume(dev);
+       /*
+        * pdev->current_state is set to PCI_D3cold during suspending,
+        * so wait until suspending completes
+        */
+       pm_runtime_barrier(dev);
+       /*
+        * Only need to resume devices in D3cold, because config
+        * registers are still accessible for devices suspended but
+        * not in D3cold.
+        */
+       if (pdev->current_state == PCI_D3cold)
+               pm_runtime_resume(dev);
+}
+
+void pci_config_pm_runtime_put(struct pci_dev *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device *parent = dev->parent;
+
+       pm_runtime_put(dev);
+       if (parent)
+               pm_runtime_put_sync(parent);
+}
+
 /**
  * pci_pm_init - Initialize PM functions of given PCI device
  * @dev: PCI device to handle.
index bacbcba..fd92aab 100644 (file)
@@ -72,6 +72,8 @@ extern void pci_disable_enabled_device(struct pci_dev *dev);
 extern int pci_finish_runtime_suspend(struct pci_dev *dev);
 extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign);
 extern void pci_wakeup_bus(struct pci_bus *bus);
+extern void pci_config_pm_runtime_get(struct pci_dev *dev);
+extern void pci_config_pm_runtime_put(struct pci_dev *dev);
 extern void pci_pm_init(struct pci_dev *dev);
 extern void platform_pci_wakeup_init(struct pci_dev *dev);
 extern void pci_allocate_cap_save_buffers(struct pci_dev *dev);
index 06bad96..af4e31c 100644 (file)
@@ -213,6 +213,7 @@ static int report_error_detected(struct pci_dev *dev, void *data)
        struct aer_broadcast_data *result_data;
        result_data = (struct aer_broadcast_data *) data;
 
+       device_lock(&dev->dev);
        dev->error_state = result_data->state;
 
        if (!dev->driver ||
@@ -231,12 +232,14 @@ static int report_error_detected(struct pci_dev *dev, void *data)
                                   dev->driver ?
                                   "no AER-aware driver" : "no driver");
                }
-               return 0;
+               goto out;
        }
 
        err_handler = dev->driver->err_handler;
        vote = err_handler->error_detected(dev, result_data->state);
        result_data->result = merge_result(result_data->result, vote);
+out:
+       device_unlock(&dev->dev);
        return 0;
 }
 
@@ -247,14 +250,17 @@ static int report_mmio_enabled(struct pci_dev *dev, void *data)
        struct aer_broadcast_data *result_data;
        result_data = (struct aer_broadcast_data *) data;
 
+       device_lock(&dev->dev);
        if (!dev->driver ||
                !dev->driver->err_handler ||
                !dev->driver->err_handler->mmio_enabled)
-               return 0;
+               goto out;
 
        err_handler = dev->driver->err_handler;
        vote = err_handler->mmio_enabled(dev);
        result_data->result = merge_result(result_data->result, vote);
+out:
+       device_unlock(&dev->dev);
        return 0;
 }
 
@@ -265,14 +271,17 @@ static int report_slot_reset(struct pci_dev *dev, void *data)
        struct aer_broadcast_data *result_data;
        result_data = (struct aer_broadcast_data *) data;
 
+       device_lock(&dev->dev);
        if (!dev->driver ||
                !dev->driver->err_handler ||
                !dev->driver->err_handler->slot_reset)
-               return 0;
+               goto out;
 
        err_handler = dev->driver->err_handler;
        vote = err_handler->slot_reset(dev);
        result_data->result = merge_result(result_data->result, vote);
+out:
+       device_unlock(&dev->dev);
        return 0;
 }
 
@@ -280,15 +289,18 @@ static int report_resume(struct pci_dev *dev, void *data)
 {
        const struct pci_error_handlers *err_handler;
 
+       device_lock(&dev->dev);
        dev->error_state = pci_channel_io_normal;
 
        if (!dev->driver ||
                !dev->driver->err_handler ||
                !dev->driver->err_handler->resume)
-               return 0;
+               goto out;
 
        err_handler = dev->driver->err_handler;
        err_handler->resume(dev);
+out:
+       device_unlock(&dev->dev);
        return 0;
 }
 
index d03a7a3..ed129b4 100644 (file)
@@ -272,7 +272,8 @@ static int get_port_device_capability(struct pci_dev *dev)
        }
 
        /* Hot-Plug Capable */
-       if (cap_mask & PCIE_PORT_SERVICE_HP) {
+       if ((cap_mask & PCIE_PORT_SERVICE_HP) &&
+           dev->pcie_flags_reg & PCI_EXP_FLAGS_SLOT) {
                pcie_capability_read_dword(dev, PCI_EXP_SLTCAP, &reg32);
                if (reg32 & PCI_EXP_SLTCAP_HPC) {
                        services |= PCIE_PORT_SERVICE_HP;
index eb907a8..9b8505c 100644 (file)
@@ -76,6 +76,8 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
        if (!access_ok(VERIFY_WRITE, buf, cnt))
                return -EINVAL;
 
+       pci_config_pm_runtime_get(dev);
+
        if ((pos & 1) && cnt) {
                unsigned char val;
                pci_user_read_config_byte(dev, pos, &val);
@@ -121,6 +123,8 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
                cnt--;
        }
 
+       pci_config_pm_runtime_put(dev);
+
        *ppos = pos;
        return nbytes;
 }
@@ -146,6 +150,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
        if (!access_ok(VERIFY_READ, buf, cnt))
                return -EINVAL;
 
+       pci_config_pm_runtime_get(dev);
+
        if ((pos & 1) && cnt) {
                unsigned char val;
                __get_user(val, buf);
@@ -191,6 +197,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
                cnt--;
        }
 
+       pci_config_pm_runtime_put(dev);
+
        *ppos = pos;
        i_size_write(ino, dp->size);
        return nbytes;
index b066273..7dd879c 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 7bf914d..390ab69 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
@@ -87,21 +96,18 @@ config PINCTRL_MMP2
        bool "MMP2 pin controller driver"
        depends on ARCH_MMP
        select PINCTRL_PXA3xx
-       select PINCONF
 
 config PINCTRL_MXS
        bool
+       select PINMUX
+       select PINCONF
 
 config PINCTRL_IMX23
        bool
-       select PINMUX
-       select PINCONF
        select PINCTRL_MXS
 
 config PINCTRL_IMX28
        bool
-       select PINMUX
-       select PINCONF
        select PINCTRL_MXS
 
 config PINCTRL_NOMADIK
@@ -126,13 +132,11 @@ config PINCTRL_PXA168
        bool "PXA168 pin controller driver"
        depends on ARCH_MMP
        select PINCTRL_PXA3xx
-       select PINCONF
 
 config PINCTRL_PXA910
        bool "PXA910 pin controller driver"
        depends on ARCH_MMP
        select PINCTRL_PXA3xx
-       select PINCONF
 
 config PINCTRL_SINGLE
        tristate "One-register-per-pin type device tree based pinctrl driver"
@@ -143,23 +147,21 @@ config PINCTRL_SINGLE
          This selects the device tree based generic pinctrl driver.
 
 config PINCTRL_SIRF
-       bool "CSR SiRFprimaII pin controller driver"
-       depends on ARCH_PRIMA2
+       bool "CSR SiRFprimaII/SiRFmarco pin controller driver"
+       depends on ARCH_SIRF
        select PINMUX
 
 config PINCTRL_TEGRA
        bool
+       select PINMUX
+       select PINCONF
 
 config PINCTRL_TEGRA20
        bool
-       select PINMUX
-       select PINCONF
        select PINCTRL_TEGRA
 
 config PINCTRL_TEGRA30
        bool
-       select PINMUX
-       select PINCONF
        select PINCTRL_TEGRA
 
 config PINCTRL_U300
@@ -178,35 +180,17 @@ config PINCTRL_COH901
          ports of 8 GPIO pins each.
 
 config PINCTRL_SAMSUNG
-       bool "Samsung pinctrl driver"
+       bool
+       depends on OF && GPIOLIB
        select PINMUX
        select PINCONF
 
 config PINCTRL_EXYNOS4
        bool "Pinctrl driver data for Exynos4 SoC"
+       depends on OF && GPIOLIB
        select PINCTRL_SAMSUNG
 
-config PINCTRL_MVEBU
-       bool
-       depends on ARCH_MVEBU
-       select PINMUX
-       select PINCONF
-
-config PINCTRL_DOVE
-       bool
-       select PINCTRL_MVEBU
-
-config PINCTRL_KIRKWOOD
-       bool
-       select PINCTRL_MVEBU
-
-config PINCTRL_ARMADA_370
-       bool
-       select PINCTRL_MVEBU
-
-config PINCTRL_ARMADA_XP
-       bool
-       select PINCTRL_MVEBU
+source "drivers/pinctrl/mvebu/Kconfig"
 
 source "drivers/pinctrl/spear/Kconfig"
 
index f395ba5..f95f5ed 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
@@ -36,12 +37,8 @@ obj-$(CONFIG_PINCTRL_U300)   += pinctrl-u300.o
 obj-$(CONFIG_PINCTRL_COH901)   += pinctrl-coh901.o
 obj-$(CONFIG_PINCTRL_SAMSUNG)  += pinctrl-samsung.o
 obj-$(CONFIG_PINCTRL_EXYNOS4)  += pinctrl-exynos.o
-obj-$(CONFIG_PINCTRL_MVEBU)    += pinctrl-mvebu.o
-obj-$(CONFIG_PINCTRL_DOVE)     += pinctrl-dove.o
-obj-$(CONFIG_PINCTRL_KIRKWOOD) += pinctrl-kirkwood.o
-obj-$(CONFIG_PINCTRL_ARMADA_370) += pinctrl-armada-370.o
-obj-$(CONFIG_PINCTRL_ARMADA_XP)  += pinctrl-armada-xp.o
 obj-$(CONFIG_PINCTRL_XWAY)     += pinctrl-xway.o
 obj-$(CONFIG_PINCTRL_LANTIQ)   += pinctrl-lantiq.o
 
+obj-$(CONFIG_PLAT_ORION)        += mvebu/
 obj-$(CONFIG_PLAT_SPEAR)       += spear/
index 0f1ec9e..5cdee86 100644 (file)
@@ -345,6 +345,62 @@ void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev,
 }
 EXPORT_SYMBOL_GPL(pinctrl_add_gpio_ranges);
 
+struct pinctrl_dev *pinctrl_find_and_add_gpio_range(const char *devname,
+               struct pinctrl_gpio_range *range)
+{
+       struct pinctrl_dev *pctldev = get_pinctrl_dev_from_devname(devname);
+
+       /*
+        * If we can't find this device, let's assume that is because
+        * it has not probed yet, so the driver trying to register this
+        * range need to defer probing.
+        */
+       if (!pctldev)
+               return ERR_PTR(-EPROBE_DEFER);
+
+       pinctrl_add_gpio_range(pctldev, range);
+       return pctldev;
+}
+EXPORT_SYMBOL_GPL(pinctrl_find_and_add_gpio_range);
+
+/**
+ * pinctrl_find_gpio_range_from_pin() - locate the GPIO range for a pin
+ * @pctldev: the pin controller device to look in
+ * @pin: a controller-local number to find the range for
+ */
+struct pinctrl_gpio_range *
+pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev,
+                                unsigned int pin)
+{
+       struct pinctrl_gpio_range *range = NULL;
+
+       /* Loop over the ranges */
+       list_for_each_entry(range, &pctldev->gpio_ranges, node) {
+               /* Check if we're in the valid range */
+               if (pin >= range->pin_base &&
+                   pin < range->pin_base + range->npins) {
+                       return range;
+               }
+       }
+
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(pinctrl_find_gpio_range_from_pin);
+
+/**
+ * pinctrl_remove_gpio_range() - remove a range of GPIOs fro a pin controller
+ * @pctldev: pin controller device to remove the range from
+ * @range: the GPIO range to remove
+ */
+void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
+                              struct pinctrl_gpio_range *range)
+{
+       mutex_lock(&pinctrl_mutex);
+       list_del(&range->node);
+       mutex_unlock(&pinctrl_mutex);
+}
+EXPORT_SYMBOL_GPL(pinctrl_remove_gpio_range);
+
 /**
  * pinctrl_get_group_selector() - returns the group selector for a group
  * @pctldev: the pin controller handling the group
@@ -563,6 +619,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 +1119,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 1f40ff6..12f5694 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 fcb1de4..fe2d1af 100644 (file)
@@ -106,6 +106,17 @@ static struct pinctrl_dev *find_pinctrl_by_of_node(struct device_node *np)
        return NULL;
 }
 
+struct pinctrl_dev *of_pinctrl_get(struct device_node *np)
+{
+       struct pinctrl_dev *pctldev;
+
+       pctldev = find_pinctrl_by_of_node(np);
+       if (!pctldev)
+               return NULL;
+
+       return pctldev;
+}
+
 static int dt_to_map_one_config(struct pinctrl *p, const char *statename,
                                struct device_node *np_config)
 {
diff --git a/drivers/pinctrl/mvebu/Kconfig b/drivers/pinctrl/mvebu/Kconfig
new file mode 100644 (file)
index 0000000..366fa54
--- /dev/null
@@ -0,0 +1,24 @@
+if PLAT_ORION
+
+config PINCTRL_MVEBU
+       bool
+       select PINMUX
+       select PINCONF
+
+config PINCTRL_DOVE
+       bool
+       select PINCTRL_MVEBU
+
+config PINCTRL_KIRKWOOD
+       bool
+       select PINCTRL_MVEBU
+
+config PINCTRL_ARMADA_370
+       bool
+       select PINCTRL_MVEBU
+
+config PINCTRL_ARMADA_XP
+       bool
+       select PINCTRL_MVEBU
+
+endif
diff --git a/drivers/pinctrl/mvebu/Makefile b/drivers/pinctrl/mvebu/Makefile
new file mode 100644 (file)
index 0000000..37c2532
--- /dev/null
@@ -0,0 +1,5 @@
+obj-$(CONFIG_PINCTRL_MVEBU)    += pinctrl-mvebu.o
+obj-$(CONFIG_PINCTRL_DOVE)     += pinctrl-dove.o
+obj-$(CONFIG_PINCTRL_KIRKWOOD) += pinctrl-kirkwood.o
+obj-$(CONFIG_PINCTRL_ARMADA_370) += pinctrl-armada-370.o
+obj-$(CONFIG_PINCTRL_ARMADA_XP)  += pinctrl-armada-xp.o
similarity index 99%
rename from drivers/pinctrl/pinctrl-mvebu.c
rename to drivers/pinctrl/mvebu/pinctrl-mvebu.c
index 8e6266c..6c44b7e 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinmux.h>
 
-#include "core.h"
 #include "pinctrl-mvebu.h"
 
 #define MPPS_PER_REG   8
index 33fbaea..833a364 100644 (file)
@@ -41,6 +41,7 @@ struct pin_config_item conf_items[] = {
        PCONFDUMP(PIN_CONFIG_DRIVE_PUSH_PULL, "output drive push pull", NULL),
        PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_DRAIN, "output drive open drain", NULL),
        PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_SOURCE, "output drive open source", NULL),
+       PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT_DISABLE, "input schmitt disabled", NULL),
        PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT, "input schmitt trigger", NULL),
        PCONFDUMP(PIN_CONFIG_INPUT_DEBOUNCE, "input debounce", "time units"),
        PCONFDUMP(PIN_CONFIG_POWER_SOURCE, "pin power source", "selector"),
index 43f474c..baee2cc 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..c5e7571
--- /dev/null
@@ -0,0 +1,1634 @@
+/*
+ * 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/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                (1 << 0)
+#define MULTI_DRIVE    (1 << 1)
+#define DEGLITCH       (1 << 2)
+#define PULL_DOWN      (1 << 3)
+#define DIS_SCHMIT     (1 << 4)
+#define DEBOUNCE       (1 << 16)
+#define DEBOUNCE_VAL_SHIFT     17
+#define DEBOUNCE_VAL   (0x3fff << DEBOUNCE_VAL_SHIFT)
+
+/**
+ * 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
+ * @get_deglitch: get deglitch status
+ * @set_deglitch: enable/disable deglitch
+ * @get_debounce: get debounce status
+ * @set_debounce: enable/disable debounce
+ * @get_pulldown: get pulldown status
+ * @set_pulldown: enable/disable pulldown
+ * @get_schmitt_trig: get schmitt trigger status
+ * @disable_schmitt_trig: disable schmitt trigger
+ * @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);
+       bool (*get_deglitch)(void __iomem *pio, unsigned pin);
+       void (*set_deglitch)(void __iomem *pio, unsigned mask, bool in_on);
+       bool (*get_debounce)(void __iomem *pio, unsigned pin, u32 *div);
+       void (*set_debounce)(void __iomem *pio, unsigned mask, bool in_on, u32 div);
+       bool (*get_pulldown)(void __iomem *pio, unsigned pin);
+       void (*set_pulldown)(void __iomem *pio, unsigned mask, bool in_on);
+       bool (*get_schmitt_trig)(void __iomem *pio, unsigned pin);
+       void (*disable_schmitt_trig)(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;
+
+       /*
+        * 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++) {
+               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 bool at91_mux_get_deglitch(void __iomem *pio, unsigned pin)
+{
+       return (__raw_readl(pio + PIO_IFSR) >> pin) & 0x1;
+}
+
+static void at91_mux_set_deglitch(void __iomem *pio, unsigned mask, bool is_on)
+{
+       __raw_writel(mask, pio + (is_on ? PIO_IFER : PIO_IFDR));
+}
+
+static void at91_mux_pio3_set_deglitch(void __iomem *pio, unsigned mask, bool is_on)
+{
+       if (is_on)
+               __raw_writel(mask, pio + PIO_IFSCDR);
+       at91_mux_set_deglitch(pio, mask, is_on);
+}
+
+static bool at91_mux_pio3_get_debounce(void __iomem *pio, unsigned pin, u32 *div)
+{
+       *div = __raw_readl(pio + PIO_SCDR);
+
+       return (__raw_readl(pio + PIO_IFSCSR) >> pin) & 0x1;
+}
+
+static void at91_mux_pio3_set_debounce(void __iomem *pio, unsigned mask,
+                               bool is_on, u32 div)
+{
+       if (is_on) {
+               __raw_writel(mask, pio + PIO_IFSCER);
+               __raw_writel(div & PIO_SCDR_DIV, pio + PIO_SCDR);
+               __raw_writel(mask, pio + PIO_IFER);
+       } else {
+               __raw_writel(mask, pio + PIO_IFDR);
+       }
+}
+
+static bool at91_mux_pio3_get_pulldown(void __iomem *pio, unsigned pin)
+{
+       return (__raw_readl(pio + PIO_PPDSR) >> pin) & 0x1;
+}
+
+static void at91_mux_pio3_set_pulldown(void __iomem *pio, unsigned mask, bool is_on)
+{
+       __raw_writel(mask, pio + (is_on ? PIO_PPDER : PIO_PPDDR));
+}
+
+static void at91_mux_pio3_disable_schmitt_trig(void __iomem *pio, unsigned mask)
+{
+       __raw_writel(__raw_readl(pio + PIO_SCHMITT) | mask, pio + PIO_SCHMITT);
+}
+
+static bool at91_mux_pio3_get_schmitt_trig(void __iomem *pio, unsigned pin)
+{
+       return (__raw_readl(pio + PIO_SCHMITT) >> pin) & 0x1;
+}
+
+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,
+       .get_deglitch   = at91_mux_get_deglitch,
+       .set_deglitch   = at91_mux_set_deglitch,
+       .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,
+       .get_deglitch   = at91_mux_get_deglitch,
+       .set_deglitch   = at91_mux_pio3_set_deglitch,
+       .get_debounce   = at91_mux_pio3_get_debounce,
+       .set_debounce   = at91_mux_pio3_set_debounce,
+       .get_pulldown   = at91_mux_pio3_get_pulldown,
+       .set_pulldown   = at91_mux_pio3_set_pulldown,
+       .get_schmitt_trig = at91_mux_pio3_get_schmitt_trig,
+       .disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig,
+       .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;
+}
+
+static 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;
+}
+
+static 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;
+       int div;
+
+       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;
+
+       if (info->ops->get_deglitch && info->ops->get_deglitch(pio, pin))
+               *config |= DEGLITCH;
+       if (info->ops->get_debounce && info->ops->get_debounce(pio, pin, &div))
+               *config |= DEBOUNCE | (div << DEBOUNCE_VAL_SHIFT);
+       if (info->ops->get_pulldown && info->ops->get_pulldown(pio, pin))
+               *config |= PULL_DOWN;
+       if (info->ops->get_schmitt_trig && info->ops->get_schmitt_trig(pio, pin))
+               *config |= DIS_SCHMIT;
+
+       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);
+
+       if (config & PULL_UP && config & PULL_DOWN)
+               return -EINVAL;
+
+       at91_mux_set_pullup(pio, mask, config & PULL_UP);
+       at91_mux_set_multidrive(pio, mask, config & MULTI_DRIVE);
+       if (info->ops->set_deglitch)
+               info->ops->set_deglitch(pio, mask, config & DEGLITCH);
+       if (info->ops->set_debounce)
+               info->ops->set_debounce(pio, mask, config & DEBOUNCE,
+                               (config & DEBOUNCE_VAL) >> DEBOUNCE_VAL_SHIFT);
+       if (info->ops->set_pulldown)
+               info->ops->set_pulldown(pio, mask, config & PULL_DOWN);
+       if (info->ops->disable_schmitt_trig && config & DIS_SCHMIT)
+               info->ops->disable_schmitt_trig(pio, mask);
+
+       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)
+{
+}
+
+static 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 = (struct at91_pinctrl_mux_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;
+}
+
+static 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;
+               }
+
+               for_each_set_bit(n, &isr, BITS_PER_LONG) {
+                       generic_handle_irq(irq_find_mapping(at91_gpio->domain, n));
+               }
+       }
+       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 int at91_gpio_irq_domain_xlate(struct irq_domain *d,
+                                     struct device_node *ctrlr,
+                                     const u32 *intspec, unsigned int intsize,
+                                     irq_hw_number_t *out_hwirq,
+                                     unsigned int *out_type)
+{
+       struct at91_gpio_chip *at91_gpio = d->host_data;
+       int ret;
+       int pin = at91_gpio->chip.base + intspec[0];
+
+       if (WARN_ON(intsize < 2))
+               return -EINVAL;
+       *out_hwirq = intspec[0];
+       *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
+
+       ret = gpio_request(pin, ctrlr->full_name);
+       if (ret)
+               return ret;
+
+       ret = gpio_direction_input(pin);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static struct irq_domain_ops at91_gpio_ops = {
+       .map    = at91_gpio_irq_map,
+       .xlate  = at91_gpio_irq_domain_xlate,
+};
+
+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, i;
+       int alias_idx = of_alias_get_id(np, "gpio");
+       uint32_t ngpio;
+       char **names;
+
+       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 = (struct at91_pinctrl_mux_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;
+       }
+
+       names = devm_kzalloc(&pdev->dev, sizeof(char*) * chip->ngpio, GFP_KERNEL);
+
+       if (!names) {
+               ret = -ENOMEM;
+               goto clk_err;
+       }
+
+       for (i = 0; i < chip->ngpio; i++)
+               names[i] = kasprintf(GFP_KERNEL, "pio%c%d", alias_idx + 'A', i);
+
+       chip->names = (const char*const*)names;
+
+       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 a4adee6..9a963ed 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/irq.h>
 #include <linux/irqdesc.h>
 #include <linux/irqdomain.h>
-#include <linux/irq.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of.h>
@@ -917,7 +916,7 @@ static int bcm2835_pinconf_set(struct pinctrl_dev *pctldev,
        return 0;
 }
 
-struct pinconf_ops bcm2835_pinconf_ops = {
+static struct pinconf_ops bcm2835_pinconf_ops = {
        .pin_config_get = bcm2835_pinconf_get,
        .pin_config_set = bcm2835_pinconf_set,
 };
@@ -960,7 +959,7 @@ static int __devinit bcm2835_pinctrl_probe(struct platform_device *pdev)
                return err;
        }
 
-       pc->base = devm_request_and_ioremap(&pdev->dev, &iomem);
+       pc->base = devm_request_and_ioremap(dev, &iomem);
        if (!pc->base)
                return -EADDRNOTAVAIL;
 
@@ -1032,7 +1031,7 @@ static int __devinit bcm2835_pinctrl_probe(struct platform_device *pdev)
        pc->pctl_dev = pinctrl_register(&bcm2835_pinctrl_desc, dev, pc);
        if (!pc->pctl_dev) {
                gpiochip_remove(&pc->gpio_chip);
-               return PTR_ERR(pc->pctl_dev);
+               return -EINVAL;
        }
 
        pc->gpio_range = bcm2835_pinctrl_gpio_range;
index b446c96..fbb3715 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;
 
-       dev_dbg(gpio->dev, "request IRQ for GPIO %d, return %d\n", offset,
-               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 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,64 +652,86 @@ 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);
        }
 }
 
+/*
+ * Here we map a GPIO in the local gpio_chip pin space to a pin in
+ * the local pinctrl pin space. The pin controller used is
+ * pinctrl-u300.
+ */
+struct coh901_pinpair {
+       unsigned int offset;
+       unsigned int pin_base;
+};
+
+#define COH901_PINRANGE(a, b) { .offset = a, .pin_base = b }
+
+static struct coh901_pinpair coh901_pintable[] = {
+       COH901_PINRANGE(10, 426),
+       COH901_PINRANGE(11, 180),
+       COH901_PINRANGE(12, 165), /* MS/MMC card insertion */
+       COH901_PINRANGE(13, 179),
+       COH901_PINRANGE(14, 178),
+       COH901_PINRANGE(16, 194),
+       COH901_PINRANGE(17, 193),
+       COH901_PINRANGE(18, 192),
+       COH901_PINRANGE(19, 191),
+       COH901_PINRANGE(20, 186),
+       COH901_PINRANGE(21, 185),
+       COH901_PINRANGE(22, 184),
+       COH901_PINRANGE(23, 183),
+       COH901_PINRANGE(24, 182),
+       COH901_PINRANGE(25, 181),
+};
+
 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 +775,28 @@ 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) {
+                       err = -ENOMEM;
+                       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);
@@ -763,32 +816,31 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
                goto err_no_chip;
        }
 
-       /* Spawn pin controller device as child of the GPIO, pass gpio chip */
-       plat->pinctrl_device->dev.platform_data = &gpio->chip;
-       err = platform_device_register(plat->pinctrl_device);
-       if (err)
-               goto err_no_pinctrl;
+       /*
+        * Add pinctrl pin ranges, the pin controller must be registered
+        * at this point
+        */
+       for (i = 0; i < ARRAY_SIZE(coh901_pintable); i++) {
+               struct coh901_pinpair *p = &coh901_pintable[i];
+
+               err = gpiochip_add_pin_range(&gpio->chip, "pinctrl-u300",
+                                            p->offset, p->pin_base, 1);
+               if (err)
+                       goto err_no_range;
+       }
 
        platform_set_drvdata(pdev, gpio);
 
        return 0;
 
-err_no_pinctrl:
+err_no_range:
        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);
+       dev_err(&pdev->dev, "module ERROR:%d\n", err);
        return err;
 }
 
@@ -806,13 +858,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 21362f4..6ff6652 100644 (file)
@@ -36,6 +36,7 @@
 /* list of external wakeup controllers supported */
 static const struct of_device_id exynos_wkup_irq_ids[] = {
        { .compatible = "samsung,exynos4210-wakeup-eint", },
+       { }
 };
 
 static void exynos_gpio_irq_unmask(struct irq_data *irqd)
index ee73059..8ed20e8 100644 (file)
@@ -322,7 +322,7 @@ static void falcon_pinconf_group_dbg_show(struct pinctrl_dev *pctrldev,
 {
 }
 
-struct pinconf_ops falcon_pinconf_ops = {
+static struct pinconf_ops falcon_pinconf_ops = {
        .pin_config_get                 = falcon_pinconf_get,
        .pin_config_set                 = falcon_pinconf_set,
        .pin_config_group_get           = falcon_pinconf_group_get,
index 63866d9..525a2c8 100644 (file)
@@ -71,7 +71,7 @@ static const struct imx_pin_reg *imx_find_pin_reg(
                        break;
        }
 
-       if (!pin_reg) {
+       if (i == info->npin_regs) {
                dev_err(info->dev, "Pin(%s): unable to find pin reg map\n",
                        info->pins[pin].name);
                return NULL;
@@ -397,7 +397,7 @@ static void imx_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
        }
 }
 
-struct pinconf_ops imx_pinconf_ops = {
+static struct pinconf_ops imx_pinconf_ops = {
        .pin_config_get = imx_pinconf_get,
        .pin_config_set = imx_pinconf_set,
        .pin_config_dbg_show = imx_pinconf_dbg_show,
index 07ba768..15f501d 100644 (file)
@@ -46,8 +46,8 @@ static int ltq_get_group_pins(struct pinctrl_dev *pctrldev,
        return 0;
 }
 
-void ltq_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
-                               struct pinctrl_map *map, unsigned num_maps)
+static void ltq_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
+                                   struct pinctrl_map *map, unsigned num_maps)
 {
        int i;
 
@@ -128,10 +128,10 @@ static int ltq_pinctrl_dt_subnode_size(struct device_node *np)
        return ret;
 }
 
-int ltq_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
-                               struct device_node *np_config,
-                               struct pinctrl_map **map,
-                               unsigned *num_maps)
+static int ltq_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+                                     struct device_node *np_config,
+                                     struct pinctrl_map **map,
+                                     unsigned *num_maps)
 {
        struct pinctrl_map *tmp;
        struct device_node *np;
@@ -275,16 +275,6 @@ static int ltq_pmx_enable(struct pinctrl_dev *pctrldev,
        return 0;
 }
 
-static void ltq_pmx_disable(struct pinctrl_dev *pctrldev,
-                               unsigned func,
-                               unsigned group)
-{
-       /*
-        * Nothing to do here. However, pinconf_check_ops() requires this
-        * callback to be defined.
-        */
-}
-
 static int ltq_pmx_gpio_request_enable(struct pinctrl_dev *pctrldev,
                                struct pinctrl_gpio_range *range,
                                unsigned pin)
@@ -312,7 +302,6 @@ static struct pinmux_ops ltq_pmx_ops = {
        .get_function_name      = ltq_pmx_func_name,
        .get_function_groups    = ltq_pmx_get_groups,
        .enable                 = ltq_pmx_enable,
-       .disable                = ltq_pmx_disable,
        .gpio_request_enable    = ltq_pmx_gpio_request_enable,
 };
 
index 4ba4636..3e7d4d6 100644 (file)
@@ -319,7 +319,7 @@ static void mxs_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
                seq_printf(s, "0x%lx", config);
 }
 
-struct pinconf_ops mxs_pinconf_ops = {
+static struct pinconf_ops mxs_pinconf_ops = {
        .pin_config_get = mxs_pinconf_get,
        .pin_config_set = mxs_pinconf_set,
        .pin_config_group_get = mxs_pinconf_group_get,
index debaa75..7d88ae3 100644 (file)
@@ -475,8 +475,10 @@ static const unsigned hsit_a_1_pins[] = { DB8500_PIN_AJ9, DB8500_PIN_AH9,
        DB8500_PIN_AG9, DB8500_PIN_AG8, DB8500_PIN_AF8 };
 static const unsigned hsit_a_2_pins[] = { DB8500_PIN_AJ9, DB8500_PIN_AH9,
        DB8500_PIN_AG9, DB8500_PIN_AG8 };
-static const unsigned clkout_a_1_pins[] = { DB8500_PIN_AH7, DB8500_PIN_AJ6 };
-static const unsigned clkout_a_2_pins[] = { DB8500_PIN_AG7, DB8500_PIN_AF7 };
+static const unsigned clkout1_a_1_pins[] = { DB8500_PIN_AH7 };
+static const unsigned clkout1_a_2_pins[] = { DB8500_PIN_AG7 };
+static const unsigned clkout2_a_1_pins[] = { DB8500_PIN_AJ6 };
+static const unsigned clkout2_a_2_pins[] = { DB8500_PIN_AF7 };
 static const unsigned usb_a_1_pins[] = { DB8500_PIN_AF28, DB8500_PIN_AE29,
        DB8500_PIN_AD29, DB8500_PIN_AC29, DB8500_PIN_AD28, DB8500_PIN_AD26,
        DB8500_PIN_AE26, DB8500_PIN_AG29, DB8500_PIN_AE27, DB8500_PIN_AD27,
@@ -592,7 +594,8 @@ static const unsigned stmmod_c_1_pins[] = { DB8500_PIN_C20, DB8500_PIN_B21,
        DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24 };
 static const unsigned usbsim_c_1_pins[] = { DB8500_PIN_D22 };
 static const unsigned mc4rstn_c_1_pins[] = { DB8500_PIN_AF25 };
-static const unsigned clkout_c_1_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AH12 };
+static const unsigned clkout1_c_1_pins[] = { DB8500_PIN_AH13 };
+static const unsigned clkout2_c_1_pins[] = { DB8500_PIN_AH12 };
 static const unsigned i2c3_c_1_pins[] = { DB8500_PIN_AG12, DB8500_PIN_AH11 };
 static const unsigned spi0_c_1_pins[] = { DB8500_PIN_AH10, DB8500_PIN_AH9,
                                          DB8500_PIN_AG9, DB8500_PIN_AG8 };
@@ -600,14 +603,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 }
 
@@ -639,6 +694,7 @@ static const struct nmk_pingroup nmk_db8500_groups[] = {
        DB8500_PIN_GROUP(i2c0_a_1, NMK_GPIO_ALT_A),
        DB8500_PIN_GROUP(ipgpio0_a_1, NMK_GPIO_ALT_A),
        DB8500_PIN_GROUP(ipgpio1_a_1, NMK_GPIO_ALT_A),
+       DB8500_PIN_GROUP(kp_a_2, NMK_GPIO_ALT_A),
        DB8500_PIN_GROUP(msp2sck_a_1, NMK_GPIO_ALT_A),
        DB8500_PIN_GROUP(msp2_a_1, NMK_GPIO_ALT_A),
        DB8500_PIN_GROUP(mc4_a_1, NMK_GPIO_ALT_A),
@@ -647,8 +703,10 @@ static const struct nmk_pingroup nmk_db8500_groups[] = {
        DB8500_PIN_GROUP(hsir_a_1, NMK_GPIO_ALT_A),
        DB8500_PIN_GROUP(hsit_a_1, NMK_GPIO_ALT_A),
        DB8500_PIN_GROUP(hsit_a_2, NMK_GPIO_ALT_A),
-       DB8500_PIN_GROUP(clkout_a_1, NMK_GPIO_ALT_A),
-       DB8500_PIN_GROUP(clkout_a_2, NMK_GPIO_ALT_A),
+       DB8500_PIN_GROUP(clkout1_a_1, NMK_GPIO_ALT_A),
+       DB8500_PIN_GROUP(clkout1_a_2, NMK_GPIO_ALT_A),
+       DB8500_PIN_GROUP(clkout2_a_1, NMK_GPIO_ALT_A),
+       DB8500_PIN_GROUP(clkout2_a_2, NMK_GPIO_ALT_A),
        DB8500_PIN_GROUP(usb_a_1, NMK_GPIO_ALT_A),
        /* Altfunction B column */
        DB8500_PIN_GROUP(trig_b_1, NMK_GPIO_ALT_B),
@@ -720,15 +778,41 @@ static const struct nmk_pingroup nmk_db8500_groups[] = {
        DB8500_PIN_GROUP(stmmod_c_1, NMK_GPIO_ALT_C),
        DB8500_PIN_GROUP(usbsim_c_1, NMK_GPIO_ALT_C),
        DB8500_PIN_GROUP(mc4rstn_c_1, NMK_GPIO_ALT_C),
-       DB8500_PIN_GROUP(clkout_c_1, NMK_GPIO_ALT_C),
+       DB8500_PIN_GROUP(clkout1_c_1, NMK_GPIO_ALT_C),
+       DB8500_PIN_GROUP(clkout2_c_1, NMK_GPIO_ALT_C),
        DB8500_PIN_GROUP(i2c3_c_1, NMK_GPIO_ALT_C),
        DB8500_PIN_GROUP(spi0_c_1, NMK_GPIO_ALT_C),
        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 +826,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
@@ -757,7 +841,7 @@ DB8500_FUNC_GROUPS(msp1, "msp1txrx_a_1", "msp1_a_1", "msp1txrx_b_1");
 DB8500_FUNC_GROUPS(lcdb, "lcdb_a_1");
 DB8500_FUNC_GROUPS(lcd, "lcdvsi0_a_1", "lcdvsi1_a_1", "lcd_d0_d7_a_1",
        "lcd_d8_d11_a_1", "lcd_d12_d23_a_1", "lcd_b_1");
-DB8500_FUNC_GROUPS(kp, "kp_a_1", "kp_b_1", "kp_b_2", "kp_c_1", "kp_oc1_1");
+DB8500_FUNC_GROUPS(kp, "kp_a_1", "kp_a_2", "kp_b_1", "kp_b_2", "kp_c_1", "kp_oc1_1");
 DB8500_FUNC_GROUPS(mc2, "mc2_a_1", "mc2rstn_c_1");
 DB8500_FUNC_GROUPS(ssp1, "ssp1_a_1");
 DB8500_FUNC_GROUPS(ssp0, "ssp0_a_1");
@@ -773,7 +857,8 @@ DB8500_FUNC_GROUPS(msp2, "msp2sck_a_1", "msp2_a_1");
 DB8500_FUNC_GROUPS(mc4, "mc4_a_1", "mc4rstn_c_1");
 DB8500_FUNC_GROUPS(mc1, "mc1_a_1", "mc1_a_2", "mc1dir_a_1");
 DB8500_FUNC_GROUPS(hsi, "hsir_a_1", "hsit_a_1", "hsit_a_2");
-DB8500_FUNC_GROUPS(clkout, "clkout_a_1", "clkout_a_2", "clkout_c_1");
+DB8500_FUNC_GROUPS(clkout, "clkout1_a_1", "clkout1_a_2", "clkout1_c_1",
+               "clkout2_a_1", "clkout2_a_2", "clkout2_c_1");
 DB8500_FUNC_GROUPS(usb, "usb_a_1");
 DB8500_FUNC_GROUPS(trig, "trig_b_1");
 DB8500_FUNC_GROUPS(i2c4, "i2c4_b_1");
@@ -784,8 +869,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 +886,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 +951,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 52fc301..bb6a401 100644 (file)
@@ -460,8 +460,10 @@ static const unsigned hsit_a_1_pins[] = { DB8540_PIN_B11, DB8540_PIN_B10,
        DB8540_PIN_E10, DB8540_PIN_B12, DB8540_PIN_D10 };
 static const unsigned hsit_a_2_pins[] = { DB8540_PIN_B11, DB8540_PIN_B10,
        DB8540_PIN_E10, DB8540_PIN_B12 };
-static const unsigned clkout_a_1_pins[] = { DB8540_PIN_D11, DB8540_PIN_AJ6 };
-static const unsigned clkout_a_2_pins[] = { DB8540_PIN_B13, DB8540_PIN_C12 };
+static const unsigned clkout1_a_1_pins[] = { DB8540_PIN_D11 };
+static const unsigned clkout1_a_2_pins[] = { DB8540_PIN_B13 };
+static const unsigned clkout2_a_1_pins[] = { DB8540_PIN_AJ6 };
+static const unsigned clkout2_a_2_pins[] = { DB8540_PIN_C12 };
 static const unsigned msp4_a_1_pins[] = { DB8540_PIN_B14, DB8540_PIN_E11 };
 static const unsigned usb_a_1_pins[] = { DB8540_PIN_D12, DB8540_PIN_D15,
        DB8540_PIN_C13, DB8540_PIN_C14, DB8540_PIN_C18, DB8540_PIN_C16,
@@ -698,8 +700,10 @@ static const struct nmk_pingroup nmk_db8540_groups[] = {
        DB8540_PIN_GROUP(hsir_a_1, NMK_GPIO_ALT_A),
        DB8540_PIN_GROUP(hsit_a_1, NMK_GPIO_ALT_A),
        DB8540_PIN_GROUP(hsit_a_2, NMK_GPIO_ALT_A),
-       DB8540_PIN_GROUP(clkout_a_1, NMK_GPIO_ALT_A),
-       DB8540_PIN_GROUP(clkout_a_2, NMK_GPIO_ALT_A),
+       DB8540_PIN_GROUP(clkout1_a_1, NMK_GPIO_ALT_A),
+       DB8540_PIN_GROUP(clkout1_a_2, NMK_GPIO_ALT_A),
+       DB8540_PIN_GROUP(clkout2_a_1, NMK_GPIO_ALT_A),
+       DB8540_PIN_GROUP(clkout2_a_2, NMK_GPIO_ALT_A),
        DB8540_PIN_GROUP(msp4_a_1, NMK_GPIO_ALT_A),
        DB8540_PIN_GROUP(usb_a_1, NMK_GPIO_ALT_A),
        /* Altfunction B column */
@@ -822,6 +826,7 @@ static const struct nmk_pingroup nmk_db8540_groups[] = {
        DB8540_PIN_GROUP(modaccuarttxrx_oc4_1, NMK_GPIO_ALT_C4),
        DB8540_PIN_GROUP(modaccuartrtscts_oc4_1, NMK_GPIO_ALT_C4),
        DB8540_PIN_GROUP(stmmod_oc4_1, NMK_GPIO_ALT_C4),
+       DB8540_PIN_GROUP(moduartstmmux_oc4_1, NMK_GPIO_ALT_C4),
 
 };
 
@@ -830,7 +835,8 @@ static const struct nmk_pingroup nmk_db8540_groups[] = {
 static const char * const a##_groups[] = { b };
 
 DB8540_FUNC_GROUPS(apetrig, "apetrig_b_1");
-DB8540_FUNC_GROUPS(clkout, "clkoutreq_a_1", "clkout_a_1", "clkout_a_2");
+DB8540_FUNC_GROUPS(clkout, "clkoutreq_a_1", "clkout1_a_1", "clkout1_a_2",
+               "clkout2_a_1", "clkout2_a_2");
 DB8540_FUNC_GROUPS(ddrtrig, "ddrtrig_b_1");
 DB8540_FUNC_GROUPS(hsi, "hsir_a_1", "hsit_a_1", "hsit_a_2");
 DB8540_FUNC_GROUPS(hwobs, "hwobs_oc4_1");
index fec9c30..8ef3e85 100644 (file)
 #include <linux/pinctrl/pinconf.h>
 /* Since we request GPIOs from ourself */
 #include <linux/pinctrl/consumer.h>
-#include <linux/mfd/dbx500-prcmu.h>
+#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"
 
 /*
@@ -47,8 +44,6 @@
  * 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;
@@ -73,10 +68,18 @@ struct nmk_gpio_chip {
        u32 lowemi;
 };
 
+/**
+ * struct nmk_pinctrl - state container for the Nomadik pin controller
+ * @dev: containing device pointer
+ * @pctl: corresponding pin controller device
+ * @soc: SoC data for this specific chip
+ * @prcm_base: PRCM register range virtual base
+ */
 struct nmk_pinctrl {
        struct device *dev;
        struct pinctrl_dev *pctl;
        const struct nmk_pinctrl_soc_data *soc;
+       void __iomem *prcm_base;
 };
 
 static struct nmk_gpio_chip *
@@ -238,6 +241,15 @@ nmk_gpio_disable_lazy_irq(struct nmk_gpio_chip *nmk_chip, unsigned offset)
        dev_dbg(nmk_chip->chip.dev, "%d: clearing interrupt mask\n", gpio);
 }
 
+static void nmk_write_masked(void __iomem *reg, u32 mask, u32 value)
+{
+       u32 val;
+
+       val = readl(reg);
+       val = ((val & ~mask) | (value & mask));
+       writel(val, reg);
+}
+
 static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct,
        unsigned offset, unsigned alt_num)
 {
@@ -276,8 +288,8 @@ static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct,
                        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)) {
-                                       prcmu_write_masked(reg, BIT(bit), 0);
+                               if (readl(npct->prcm_base + reg) & BIT(bit)) {
+                                       nmk_write_masked(npct->prcm_base + reg, BIT(bit), 0);
                                        dev_dbg(npct->dev,
                                                "PRCM GPIOCR: pin %i: alternate-C%i has been disabled\n",
                                                offset, i+1);
@@ -305,8 +317,8 @@ static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct,
                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)) {
-                               prcmu_write_masked(reg, BIT(bit), 0);
+                       if (readl(npct->prcm_base + reg) & BIT(bit)) {
+                               nmk_write_masked(npct->prcm_base + reg, BIT(bit), 0);
                                dev_dbg(npct->dev,
                                        "PRCM GPIOCR: pin %i: alternate-C%i has been disabled\n",
                                        offset, i+1);
@@ -318,7 +330,7 @@ static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct,
        bit = pin_desc->altcx[alt_index].control_bit;
        dev_dbg(npct->dev, "PRCM GPIOCR: pin %i: alternate-C%i has been selected\n",
                offset, alt_index+1);
-       prcmu_write_masked(reg, BIT(bit), BIT(bit));
+       nmk_write_masked(npct->prcm_base + reg, BIT(bit), BIT(bit));
 }
 
 static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
@@ -523,7 +535,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
@@ -662,6 +674,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 (readl(npct->prcm_base + 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;
@@ -1043,15 +1084,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 =
@@ -1065,12 +1107,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)",
@@ -1114,13 +1162,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)
 {
@@ -1237,8 +1286,8 @@ void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up)
        }
 }
 
-int nmk_gpio_irq_map(struct irq_domain *d, unsigned int irq,
-                         irq_hw_number_t hwirq)
+static int nmk_gpio_irq_map(struct irq_domain *d, unsigned int irq,
+                           irq_hw_number_t hwirq)
 {
        struct nmk_gpio_chip *nmk_chip = d->host_data;
 
@@ -1268,6 +1317,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
        struct clk *clk;
        int secondary_irq;
        void __iomem *base;
+       int irq_start = 0;
        int irq;
        int ret;
 
@@ -1371,19 +1421,11 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
 
        platform_set_drvdata(dev, nmk_chip);
 
-       if (np) {
-               /* The DT case will just grab a set of IRQ numbers */
-               nmk_chip->domain = irq_domain_add_linear(np, NMK_GPIO_PER_CHIP,
-                               &nmk_gpio_irq_simple_ops, nmk_chip);
-       } else {
-               /* Non-DT legacy mode, use hardwired IRQ numbers */
-               int irq_start;
-
+       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) {
                dev_err(&dev->dev, "failed to create irqdomain\n");
                ret = -ENOSYS;
@@ -1458,7 +1500,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 = {
@@ -1629,9 +1671,9 @@ static void nmk_pmx_disable(struct pinctrl_dev *pctldev,
        dev_dbg(npct->dev, "disable group %s, %u pins\n", g->name, g->npins);
 }
 
-int nmk_gpio_request_enable(struct pinctrl_dev *pctldev,
-                           struct pinctrl_gpio_range *range,
-                           unsigned offset)
+static int nmk_gpio_request_enable(struct pinctrl_dev *pctldev,
+                                  struct pinctrl_gpio_range *range,
+                                  unsigned offset)
 {
        struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
        struct nmk_gpio_chip *nmk_chip;
@@ -1660,9 +1702,9 @@ int nmk_gpio_request_enable(struct pinctrl_dev *pctldev,
        return 0;
 }
 
-void nmk_gpio_disable_free(struct pinctrl_dev *pctldev,
-                          struct pinctrl_gpio_range *range,
-                          unsigned offset)
+static void nmk_gpio_disable_free(struct pinctrl_dev *pctldev,
+                                 struct pinctrl_gpio_range *range,
+                                 unsigned offset)
 {
        struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev);
 
@@ -1680,17 +1722,15 @@ static struct pinmux_ops nmk_pinmux_ops = {
        .gpio_disable_free = nmk_gpio_disable_free,
 };
 
-int nmk_pin_config_get(struct pinctrl_dev *pctldev,
-                      unsigned pin,
-                      unsigned long *config)
+static int nmk_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin,
+                             unsigned long *config)
 {
        /* Not implemented */
        return -EINVAL;
 }
 
-int nmk_pin_config_set(struct pinctrl_dev *pctldev,
-                      unsigned pin,
-                      unsigned long config)
+static int nmk_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
+                             unsigned long config)
 {
        static const char *pullnames[] = {
                [NMK_GPIO_PULL_NONE]    = "none",
@@ -1812,6 +1852,7 @@ static int __devinit nmk_pinctrl_probe(struct platform_device *pdev)
        const struct platform_device_id *platid = platform_get_device_id(pdev);
        struct device_node *np = pdev->dev.of_node;
        struct nmk_pinctrl *npct;
+       struct resource *res;
        unsigned int version = 0;
        int i;
 
@@ -1821,9 +1862,14 @@ static int __devinit nmk_pinctrl_probe(struct platform_device *pdev)
 
        if (platid)
                version = platid->driver_data;
-       else if (np)
-               version = (unsigned int)
-                       of_match_device(nmk_pinctrl_match, &pdev->dev)->data;
+       else if (np) {
+               const struct of_device_id *match;
+
+               match = of_match_device(nmk_pinctrl_match, &pdev->dev);
+               if (!match)
+                       return -ENODEV;
+               version = (unsigned int) match->data;
+       }
 
        /* Poke in other ASIC variants here */
        if (version == PINCTRL_NMK_STN8815)
@@ -1833,22 +1879,37 @@ static int __devinit nmk_pinctrl_probe(struct platform_device *pdev)
        if (version == PINCTRL_NMK_DB8540)
                nmk_pinctrl_db8540_init(&npct->soc);
 
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res) {
+               npct->prcm_base = devm_ioremap(&pdev->dev, res->start,
+                                              resource_size(res));
+               if (!npct->prcm_base) {
+                       dev_err(&pdev->dev,
+                               "failed to ioremap PRCM registers\n");
+                       return -ENOMEM;
+               }
+       } else {
+               dev_info(&pdev->dev,
+                        "No PRCM base, assume no ALT-Cx control is available\n");
+       }
+
        /*
         * 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 < 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;
        nmk_pinctrl_desc.npins = npct->soc->npins;
        npct->dev = &pdev->dev;
+
        npct->pctl = pinctrl_register(&nmk_pinctrl_desc, &pdev->dev, npct);
        if (!npct->pctl) {
                dev_err(&pdev->dev, "could not register Nomadik pinctrl driver\n");
@@ -1883,6 +1944,7 @@ static const struct platform_device_id nmk_pinctrl_id[] = {
        { "pinctrl-stn8815", PINCTRL_NMK_STN8815 },
        { "pinctrl-db8500", PINCTRL_NMK_DB8500 },
        { "pinctrl-db8540", PINCTRL_NMK_DB8540 },
+       { }
 };
 
 static struct platform_driver nmk_pinctrl_driver = {
index eef316e..bcd4191 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 f14cd6b..51f8a38 100644 (file)
@@ -173,7 +173,6 @@ int pxa3xx_pinctrl_register(struct platform_device *pdev,
 {
        struct pinctrl_desc *desc;
        struct resource *res;
-       int ret = 0;
 
        if (!info || !info->cputype)
                return -EINVAL;
@@ -188,23 +187,17 @@ int pxa3xx_pinctrl_register(struct platform_device *pdev,
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res)
                return -ENOENT;
-       info->phy_base = res->start;
-       info->phy_size = resource_size(res);
-       info->virt_base = ioremap(info->phy_base, info->phy_size);
+       info->virt_base = devm_request_and_ioremap(&pdev->dev, res);
        if (!info->virt_base)
                return -ENOMEM;
        info->pctrl = pinctrl_register(desc, &pdev->dev, info);
        if (!info->pctrl) {
                dev_err(&pdev->dev, "failed to register PXA pinmux driver\n");
-               ret = -EINVAL;
-               goto err;
+               return -EINVAL;
        }
        pinctrl_add_gpio_range(info->pctrl, &pxa3xx_pinctrl_gpio_range);
        platform_set_drvdata(pdev, info);
        return 0;
-err:
-       iounmap(info->virt_base);
-       return ret;
 }
 
 int pxa3xx_pinctrl_unregister(struct platform_device *pdev)
@@ -212,7 +205,6 @@ int pxa3xx_pinctrl_unregister(struct platform_device *pdev)
        struct pxa3xx_pinmux_info *info = platform_get_drvdata(pdev);
 
        pinctrl_unregister(info->pctrl);
-       iounmap(info->virt_base);
        platform_set_drvdata(pdev, NULL);
        return 0;
 }
index 8135744..92fad08 100644 (file)
@@ -60,8 +60,6 @@ struct pxa3xx_pinmux_info {
        struct device *dev;
        struct pinctrl_dev *pctrl;
        enum pxa_cpu_type cputype;
-       unsigned int phy_base;
-       unsigned int phy_size;
        void __iomem *virt_base;
 
        struct pxa3xx_mfp_pin *mfp;
index dd108a9..861cd5f 100644 (file)
@@ -513,7 +513,7 @@ static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
  * 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.
  */
-static int __init samsung_pinctrl_parse_dt_pins(struct platform_device *pdev,
+static int __devinit samsung_pinctrl_parse_dt_pins(struct platform_device *pdev,
                        struct device_node *cfg_np, struct pinctrl_desc *pctl,
                        unsigned int **pin_list, unsigned int *npins)
 {
@@ -560,7 +560,7 @@ static int __init samsung_pinctrl_parse_dt_pins(struct platform_device *pdev,
  * from device node of the pin-controller. A pin group is formed with all
  * the pins listed in the "samsung,pins" property.
  */
-static int __init samsung_pinctrl_parse_dt(struct platform_device *pdev,
+static int __devinit samsung_pinctrl_parse_dt(struct platform_device *pdev,
                                struct samsung_pinctrl_drv_data *drvdata)
 {
        struct device *dev = &pdev->dev;
@@ -655,7 +655,7 @@ static int __init samsung_pinctrl_parse_dt(struct platform_device *pdev,
 }
 
 /* register the pinctrl interface with the pinctrl subsystem */
-static int __init samsung_pinctrl_register(struct platform_device *pdev,
+static int __devinit samsung_pinctrl_register(struct platform_device *pdev,
                                struct samsung_pinctrl_drv_data *drvdata)
 {
        struct pinctrl_desc *ctrldesc = &drvdata->pctl;
@@ -729,7 +729,7 @@ static int __init samsung_pinctrl_register(struct platform_device *pdev,
 }
 
 /* register the gpiolib interface with the gpiolib subsystem */
-static int __init samsung_gpiolib_register(struct platform_device *pdev,
+static int __devinit samsung_gpiolib_register(struct platform_device *pdev,
                                struct samsung_pinctrl_drv_data *drvdata)
 {
        struct gpio_chip *gc;
@@ -762,7 +762,7 @@ static int __init samsung_gpiolib_register(struct platform_device *pdev,
 }
 
 /* unregister the gpiolib interface with the gpiolib subsystem */
-static int __init samsung_gpiolib_unregister(struct platform_device *pdev,
+static int __devinit samsung_gpiolib_unregister(struct platform_device *pdev,
                                struct samsung_pinctrl_drv_data *drvdata)
 {
        int ret = gpiochip_remove(drvdata->gc);
index 726a729..5549463 100644 (file)
@@ -30,6 +30,7 @@
 #define PCS_MUX_BITS_NAME              "pinctrl-single,bits"
 #define PCS_REG_NAME_LEN               ((sizeof(unsigned long) * 2) + 1)
 #define PCS_OFF_DISABLED               ~0U
+#define PCS_MAX_GPIO_VALUES            2
 
 /**
  * struct pcs_pingroup - pingroups for a function
@@ -77,6 +78,16 @@ struct pcs_function {
 };
 
 /**
+ * struct pcs_gpio_range - pinctrl gpio range
+ * @range:     subrange of the GPIO number space
+ * @gpio_func: gpio function value in the pinmux register
+ */
+struct pcs_gpio_range {
+       struct pinctrl_gpio_range range;
+       int gpio_func;
+};
+
+/**
  * struct pcs_data - wrapper for data needed by pinctrl framework
  * @pa:                pindesc array
  * @cur:       index to current element
@@ -244,15 +255,15 @@ static int pcs_get_group_pins(struct pinctrl_dev *pctldev,
 
 static void pcs_pin_dbg_show(struct pinctrl_dev *pctldev,
                                        struct seq_file *s,
-                                       unsigned offset)
+                                       unsigned pin)
 {
        struct pcs_device *pcs;
-       unsigned val;
+       unsigned val, mux_bytes;
 
        pcs = pinctrl_dev_get_drvdata(pctldev);
 
-       val = pcs->read(pcs->base + offset);
-       val &= pcs->fmask;
+       mux_bytes = pcs->width / BITS_PER_BYTE;
+       val = pcs->read(pcs->base + pin * mux_bytes);
 
        seq_printf(s, "%08x %s " , val, DRIVER_NAME);
 }
@@ -403,9 +414,26 @@ static void pcs_disable(struct pinctrl_dev *pctldev, unsigned fselector,
 }
 
 static int pcs_request_gpio(struct pinctrl_dev *pctldev,
-                       struct pinctrl_gpio_range *range, unsigned offset)
+                           struct pinctrl_gpio_range *range, unsigned pin)
 {
-       return -ENOTSUPP;
+       struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
+       struct pcs_gpio_range *gpio = NULL;
+       int end, mux_bytes;
+       unsigned data;
+
+       gpio = container_of(range, struct pcs_gpio_range, range);
+       end = range->pin_base + range->npins - 1;
+       if (pin < range->pin_base || pin > end) {
+               dev_err(pctldev->dev,
+                       "pin %d isn't in the range of %d to %d\n",
+                       pin, range->pin_base, end);
+               return -EINVAL;
+       }
+       mux_bytes = pcs->width / BITS_PER_BYTE;
+       data = pcs->read(pcs->base + pin * mux_bytes) & ~pcs->fmask;
+       data |= gpio->gpio_func;
+       pcs->write(data, pcs->base + pin * mux_bytes);
+       return 0;
 }
 
 static struct pinmux_ops pcs_pinmux_ops = {
@@ -772,7 +800,7 @@ static int pcs_dt_node_to_map(struct pinctrl_dev *pctldev,
        pcs = pinctrl_dev_get_drvdata(pctldev);
 
        *map = devm_kzalloc(pcs->dev, sizeof(**map), GFP_KERNEL);
-       if (!map)
+       if (!*map)
                return -ENOMEM;
 
        *num_maps = 0;
@@ -879,6 +907,50 @@ static void pcs_free_resources(struct pcs_device *pcs)
 
 static struct of_device_id pcs_of_match[];
 
+static int __devinit pcs_add_gpio_range(struct device_node *node,
+                                       struct pcs_device *pcs)
+{
+       struct pcs_gpio_range *gpio;
+       struct device_node *child;
+       struct resource r;
+       const char name[] = "pinctrl-single";
+       u32 gpiores[PCS_MAX_GPIO_VALUES];
+       int ret, i = 0, mux_bytes = 0;
+
+       for_each_child_of_node(node, child) {
+               ret = of_address_to_resource(child, 0, &r);
+               if (ret < 0)
+                       continue;
+               memset(gpiores, 0, sizeof(u32) * PCS_MAX_GPIO_VALUES);
+               ret = of_property_read_u32_array(child, "pinctrl-single,gpio",
+                                                gpiores, PCS_MAX_GPIO_VALUES);
+               if (ret < 0)
+                       continue;
+               gpio = devm_kzalloc(pcs->dev, sizeof(*gpio), GFP_KERNEL);
+               if (!gpio) {
+                       dev_err(pcs->dev, "failed to allocate pcs gpio\n");
+                       return -ENOMEM;
+               }
+               gpio->range.name = devm_kzalloc(pcs->dev, sizeof(name),
+                                               GFP_KERNEL);
+               if (!gpio->range.name) {
+                       dev_err(pcs->dev, "failed to allocate range name\n");
+                       return -ENOMEM;
+               }
+               memcpy((char *)gpio->range.name, name, sizeof(name));
+
+               gpio->range.id = i++;
+               gpio->range.base = gpiores[0];
+               gpio->gpio_func = gpiores[1];
+               mux_bytes = pcs->width / BITS_PER_BYTE;
+               gpio->range.pin_base = (r.start - pcs->res->start) / mux_bytes;
+               gpio->range.npins = (r.end - r.start) / mux_bytes + 1;
+
+               pinctrl_add_gpio_range(pcs->pctl, &gpio->range);
+       }
+       return 0;
+}
+
 static int __devinit pcs_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
@@ -975,6 +1047,10 @@ static int __devinit pcs_probe(struct platform_device *pdev)
                goto free;
        }
 
+       ret = pcs_add_gpio_range(np, pcs);
+       if (ret < 0)
+               goto free;
+
        dev_info(pcs->dev, "%i pins at pa %p size %u\n",
                 pcs->desc.npins, pcs->base, pcs->size);
 
index 675497c..a3905e5 100644 (file)
 #define SIRFSOC_NUM_PADS    622
 #define SIRFSOC_RSC_PIN_MUX 0x4
 
-#define SIRFSOC_GPIO_PAD_EN(g) ((g)*0x100 + 0x84)
+#define SIRFSOC_GPIO_PAD_EN(g)         ((g)*0x100 + 0x84)
+#define SIRFSOC_GPIO_PAD_EN_CLR(g)     ((g)*0x100 + 0x90)
 #define SIRFSOC_GPIO_CTRL(g, i)                        ((g)*0x100 + (i)*4)
 #define SIRFSOC_GPIO_DSP_EN0                   (0x80)
-#define SIRFSOC_GPIO_PAD_EN(g)                 ((g)*0x100 + 0x84)
 #define SIRFSOC_GPIO_INT_STATUS(g)             ((g)*0x100 + 0x8C)
 
 #define SIRFSOC_GPIO_CTL_INTR_LOW_MASK         0x1
@@ -60,6 +60,7 @@ struct sirfsoc_gpio_bank {
        int id;
        int parent_irq;
        spinlock_t lock;
+       bool is_marco; /* for marco, some registers are different with prima2 */
 };
 
 static struct sirfsoc_gpio_bank sgpio_bank[SIRFSOC_GPIO_NO_OF_BANKS];
@@ -191,6 +192,7 @@ struct sirfsoc_pmx {
        struct pinctrl_dev *pmx;
        void __iomem *gpio_virtbase;
        void __iomem *rsc_virtbase;
+       bool is_marco;
 };
 
 /* SIRFSOC_GPIO_PAD_EN set */
@@ -1088,12 +1090,21 @@ static void sirfsoc_pinmux_endisable(struct sirfsoc_pmx *spmx, unsigned selector
 
        for (i = 0; i < mux->muxmask_counts; i++) {
                u32 muxval;
-               muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
-               if (enable)
-                       muxval = muxval & ~mask[i].mask;
-               else
-                       muxval = muxval | mask[i].mask;
-               writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
+               if (!spmx->is_marco) {
+                       muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
+                       if (enable)
+                               muxval = muxval & ~mask[i].mask;
+                       else
+                               muxval = muxval | mask[i].mask;
+                       writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
+               } else {
+                       if (enable)
+                               writel(mask[i].mask, spmx->gpio_virtbase +
+                                       SIRFSOC_GPIO_PAD_EN_CLR(mask[i].group));
+                       else
+                               writel(mask[i].mask, spmx->gpio_virtbase +
+                                       SIRFSOC_GPIO_PAD_EN(mask[i].group));
+               }
        }
 
        if (mux->funcmask && enable) {
@@ -1158,9 +1169,14 @@ static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev,
 
        spmx = pinctrl_dev_get_drvdata(pmxdev);
 
-       muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
-       muxval = muxval | (1 << (offset - range->pin_base));
-       writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
+       if (!spmx->is_marco) {
+               muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
+               muxval = muxval | (1 << (offset - range->pin_base));
+               writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
+       } else {
+               writel(1 << (offset - range->pin_base), spmx->gpio_virtbase +
+                       SIRFSOC_GPIO_PAD_EN(group));
+       }
 
        return 0;
 }
@@ -1218,6 +1234,7 @@ static void __iomem *sirfsoc_rsc_of_iomap(void)
 {
        const struct of_device_id rsc_ids[]  = {
                { .compatible = "sirf,prima2-rsc" },
+               { .compatible = "sirf,marco-rsc" },
                {}
        };
        struct device_node *np;
@@ -1259,6 +1276,9 @@ static int __devinit sirfsoc_pinmux_probe(struct platform_device *pdev)
                goto out_no_rsc_remap;
        }
 
+       if (of_device_is_compatible(np, "sirf,marco-pinctrl"))
+               spmx->is_marco = 1;
+
        /* Now register the pin controller and all pins it handles */
        spmx->pmx = pinctrl_register(&sirfsoc_pinmux_desc, &pdev->dev, spmx);
        if (!spmx->pmx) {
@@ -1287,6 +1307,7 @@ out_no_gpio_remap:
 
 static const struct of_device_id pinmux_ids[] __devinitconst = {
        { .compatible = "sirf,prima2-pinctrl" },
+       { .compatible = "sirf,marco-pinctrl" },
        {}
 };
 
@@ -1323,41 +1344,6 @@ static inline struct sirfsoc_gpio_bank *sirfsoc_gpio_to_bank(unsigned int gpio)
        return &sgpio_bank[gpio / SIRFSOC_GPIO_BANK_SIZE];
 }
 
-void sirfsoc_gpio_set_pull(unsigned gpio, unsigned mode)
-{
-       struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(gpio);
-       int idx = sirfsoc_gpio_to_offset(gpio);
-       u32 val, offset;
-       unsigned long flags;
-
-       offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
-
-       spin_lock_irqsave(&sgpio_lock, flags);
-
-       val = readl(bank->chip.regs + offset);
-
-       switch (mode) {
-       case SIRFSOC_GPIO_PULL_NONE:
-               val &= ~SIRFSOC_GPIO_CTL_PULL_MASK;
-               break;
-       case SIRFSOC_GPIO_PULL_UP:
-               val |= SIRFSOC_GPIO_CTL_PULL_MASK;
-               val |= SIRFSOC_GPIO_CTL_PULL_HIGH;
-               break;
-       case SIRFSOC_GPIO_PULL_DOWN:
-               val |= SIRFSOC_GPIO_CTL_PULL_MASK;
-               val &= ~SIRFSOC_GPIO_CTL_PULL_HIGH;
-               break;
-       default:
-               break;
-       }
-
-       writel(val, bank->chip.regs + offset);
-
-       spin_unlock_irqrestore(&sgpio_lock, flags);
-}
-EXPORT_SYMBOL(sirfsoc_gpio_set_pull);
-
 static inline struct sirfsoc_gpio_bank *sirfsoc_irqchip_to_bank(struct gpio_chip *chip)
 {
        return container_of(to_of_mm_gpio_chip(chip), struct sirfsoc_gpio_bank, chip);
@@ -1656,8 +1642,8 @@ static void sirfsoc_gpio_set_value(struct gpio_chip *chip, unsigned offset,
        spin_unlock_irqrestore(&bank->lock, flags);
 }
 
-int sirfsoc_gpio_irq_map(struct irq_domain *d, unsigned int irq,
-       irq_hw_number_t hwirq)
+static int sirfsoc_gpio_irq_map(struct irq_domain *d, unsigned int irq,
+                               irq_hw_number_t hwirq)
 {
        struct sirfsoc_gpio_bank *bank = d->host_data;
 
@@ -1683,6 +1669,7 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np)
        struct sirfsoc_gpio_bank *bank;
        void *regs;
        struct platform_device *pdev;
+       bool is_marco = false;
 
        pdev = of_find_device_by_node(np);
        if (!pdev)
@@ -1692,6 +1679,9 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np)
        if (!regs)
                return -ENOMEM;
 
+       if (of_device_is_compatible(np, "sirf,marco-pinctrl"))
+               is_marco = 1;
+
        for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
                bank = &sgpio_bank[i];
                spin_lock_init(&bank->lock);
@@ -1708,6 +1698,7 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np)
                bank->chip.gc.of_node = np;
                bank->chip.regs = regs;
                bank->id = i;
+               bank->is_marco = is_marco;
                bank->parent_irq = platform_get_irq(pdev, i);
                if (bank->parent_irq < 0) {
                        err = bank->parent_irq;
index 729b686..e9f80a5 100644 (file)
@@ -178,8 +178,9 @@ static int add_config(struct device *dev, unsigned long **configs,
        return 0;
 }
 
-void tegra_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
-                              struct pinctrl_map *map, unsigned num_maps)
+static void tegra_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
+                                     struct pinctrl_map *map,
+                                     unsigned num_maps)
 {
        int i;
 
@@ -209,11 +210,11 @@ static const struct cfg_param {
        {"nvidia,slew-rate-rising",     TEGRA_PINCONF_PARAM_SLEW_RATE_RISING},
 };
 
-int tegra_pinctrl_dt_subnode_to_map(struct device *dev,
-                                   struct device_node *np,
-                                   struct pinctrl_map **map,
-                                   unsigned *reserved_maps,
-                                   unsigned *num_maps)
+static int tegra_pinctrl_dt_subnode_to_map(struct device *dev,
+                                          struct device_node *np,
+                                          struct pinctrl_map **map,
+                                          unsigned *reserved_maps,
+                                          unsigned *num_maps)
 {
        int ret, i;
        const char *function;
@@ -288,9 +289,10 @@ exit:
        return ret;
 }
 
-int tegra_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
-                                struct device_node *np_config,
-                                struct pinctrl_map **map, unsigned *num_maps)
+static int tegra_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+                                       struct device_node *np_config,
+                                       struct pinctrl_map **map,
+                                       unsigned *num_maps)
 {
        unsigned reserved_maps;
        struct device_node *np;
@@ -464,7 +466,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;
@@ -660,7 +662,7 @@ static void tegra_pinconf_config_dbg_show(struct pinctrl_dev *pctldev,
 }
 #endif
 
-struct pinconf_ops tegra_pinconf_ops = {
+static struct pinconf_ops tegra_pinconf_ops = {
        .pin_config_get = tegra_pinconf_get,
        .pin_config_set = tegra_pinconf_set,
        .pin_config_group_get = tegra_pinconf_group_get,
index 0386fdf..7894f14 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 309f5b9..b84de03 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;
 };
 
@@ -1013,52 +1011,11 @@ static struct pinmux_ops u300_pmx_ops = {
        .disable = u300_pmx_disable,
 };
 
-/*
- * GPIO ranges handled by the application-side COH901XXX GPIO controller
- * Very many pins can be converted into GPIO pins, but we only list those
- * that are useful in practice to cut down on tables.
- */
-#define U300_GPIO_RANGE(a, b, c) { .name = "COH901XXX", .id = a, .base= a, \
-                       .pin_base = b, .npins = c }
-
-static struct pinctrl_gpio_range u300_gpio_ranges[] = {
-       U300_GPIO_RANGE(10, 426, 1),
-       U300_GPIO_RANGE(11, 180, 1),
-       U300_GPIO_RANGE(12, 165, 1), /* MS/MMC card insertion */
-       U300_GPIO_RANGE(13, 179, 1),
-       U300_GPIO_RANGE(14, 178, 1),
-       U300_GPIO_RANGE(16, 194, 1),
-       U300_GPIO_RANGE(17, 193, 1),
-       U300_GPIO_RANGE(18, 192, 1),
-       U300_GPIO_RANGE(19, 191, 1),
-       U300_GPIO_RANGE(20, 186, 1),
-       U300_GPIO_RANGE(21, 185, 1),
-       U300_GPIO_RANGE(22, 184, 1),
-       U300_GPIO_RANGE(23, 183, 1),
-       U300_GPIO_RANGE(24, 182, 1),
-       U300_GPIO_RANGE(25, 181, 1),
-};
-
-static struct pinctrl_gpio_range *u300_match_gpio_range(unsigned pin)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++) {
-               struct pinctrl_gpio_range *range;
-
-               range = &u300_gpio_ranges[i];
-               if (pin >= range->pin_base &&
-                   pin <= (range->pin_base + range->npins - 1))
-                       return range;
-       }
-       return NULL;
-}
-
-int u300_pin_config_get(struct pinctrl_dev *pctldev,
-                       unsigned pin,
-                       unsigned long *config)
+static int u300_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin,
+                              unsigned long *config)
 {
-       struct pinctrl_gpio_range *range = u300_match_gpio_range(pin);
+       struct pinctrl_gpio_range *range =
+               pinctrl_find_gpio_range_from_pin(pctldev, pin);
 
        /* We get config for those pins we CAN get it for and that's it */
        if (!range)
@@ -1069,11 +1026,11 @@ int u300_pin_config_get(struct pinctrl_dev *pctldev,
                                    config);
 }
 
-int u300_pin_config_set(struct pinctrl_dev *pctldev,
-                       unsigned pin,
-                       unsigned long config)
+static int u300_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
+                              unsigned long config)
 {
-       struct pinctrl_gpio_range *range = u300_match_gpio_range(pin);
+       struct pinctrl_gpio_range *range =
+               pinctrl_find_gpio_range_from_pin(pctldev, pin);
        int ret;
 
        if (!range)
@@ -1109,9 +1066,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 */
        upmx = devm_kzalloc(&pdev->dev, sizeof(*upmx), GFP_KERNEL);
@@ -1123,32 +1077,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;
-       }
-
-       /* We will handle a range of GPIO pins */
-       for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++) {
-               u300_gpio_ranges[i].gc = gpio_chip;
-               pinctrl_add_gpio_range(upmx->pctl, &u300_gpio_ranges[i]);
+               return -EINVAL;
        }
 
        platform_set_drvdata(pdev, upmx);
@@ -1156,14 +1093,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 +1100,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 f8d917d..ad90984 100644 (file)
@@ -17,8 +17,6 @@
 #include <linux/ioport.h>
 #include <linux/io.h>
 #include <linux/device.h>
-#include <linux/module.h>
-#include <linux/io.h>
 #include <linux/platform_device.h>
 
 #include "pinctrl-lantiq.h"
@@ -524,7 +522,7 @@ static int xway_pinconf_set(struct pinctrl_dev *pctldev,
        return 0;
 }
 
-struct pinconf_ops xway_pinconf_ops = {
+static struct pinconf_ops xway_pinconf_ops = {
        .pin_config_get = xway_pinconf_get,
        .pin_config_set = xway_pinconf_set,
 };
index 9301a7a..1a00658 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,18 @@ 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));
+                       goto err_pin_request;
+               }
+       }
+
+       /* 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) {
@@ -457,8 +425,26 @@ int pinmux_enable_setting(struct pinctrl_setting const *setting)
                desc->mux_setting = &(setting->data.mux);
        }
 
-       return ops->enable(pctldev, setting->data.mux.func,
-                          setting->data.mux.group);
+       ret = ops->enable(pctldev, setting->data.mux.func,
+                         setting->data.mux.group);
+
+       if (ret)
+               goto err_enable;
+
+       return 0;
+
+err_enable:
+       for (i = 0; i < num_pins; i++) {
+               desc = pin_desc_get(pctldev, pins[i]);
+               if (desc)
+                       desc->mux_setting = NULL;
+       }
+err_pin_request:
+       /* On error release all taken pins */
+       while (--i >= 0)
+               pin_free(pctldev, pins[i], NULL);
+
+       return ret;
 }
 
 void pinmux_disable_setting(struct pinctrl_setting const *setting)
@@ -482,6 +468,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 +480,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 9155879..04d93e6 100644 (file)
@@ -25,20 +25,31 @@ config PINCTRL_SPEAR310
        bool "ST Microelectronics SPEAr310 SoC pin controller driver"
        depends on MACH_SPEAR310
        select PINCTRL_SPEAR3XX
+       select PINCTRL_SPEAR_PLGPIO
 
 config PINCTRL_SPEAR320
        bool "ST Microelectronics SPEAr320 SoC pin controller driver"
        depends on MACH_SPEAR320
        select PINCTRL_SPEAR3XX
+       select PINCTRL_SPEAR_PLGPIO
 
 config PINCTRL_SPEAR1310
        bool "ST Microelectronics SPEAr1310 SoC pin controller driver"
        depends on MACH_SPEAR1310
        select PINCTRL_SPEAR
+       select PINCTRL_SPEAR_PLGPIO
 
 config PINCTRL_SPEAR1340
        bool "ST Microelectronics SPEAr1340 SoC pin controller driver"
        depends on MACH_SPEAR1340
        select PINCTRL_SPEAR
+       select PINCTRL_SPEAR_PLGPIO
+
+config PINCTRL_SPEAR_PLGPIO
+       bool "SPEAr SoC PLGPIO Controller"
+       depends on GPIOLIB && PINCTRL_SPEAR
+       help
+         Say yes here to support PLGPIO controller on ST Microelectronics SPEAr
+         SoCs.
 
 endif
index b28a7ba..0e400eb 100644 (file)
@@ -1,5 +1,6 @@
 # SPEAr pinmux support
 
+obj-$(CONFIG_PINCTRL_SPEAR_PLGPIO)     += pinctrl-plgpio.o
 obj-$(CONFIG_PINCTRL_SPEAR)    += pinctrl-spear.o
 obj-$(CONFIG_PINCTRL_SPEAR3XX) += pinctrl-spear3xx.o
 obj-$(CONFIG_PINCTRL_SPEAR300) += pinctrl-spear300.o
diff --git a/drivers/pinctrl/spear/pinctrl-plgpio.c b/drivers/pinctrl/spear/pinctrl-plgpio.c
new file mode 100644 (file)
index 0000000..4c04505
--- /dev/null
@@ -0,0 +1,758 @@
+/*
+ * SPEAr platform PLGPIO driver
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@linaro.org>
+ *
+ * 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/clk.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/spinlock.h>
+#include <asm/mach/irq.h>
+
+#define MAX_GPIO_PER_REG               32
+#define PIN_OFFSET(pin)                        (pin % MAX_GPIO_PER_REG)
+#define REG_OFFSET(base, reg, pin)     (base + reg + (pin / MAX_GPIO_PER_REG) \
+                                                       * sizeof(int *))
+
+/*
+ * plgpio pins in all machines are not one to one mapped, bitwise with registers
+ * bits. These set of macros define register masks for which below functions
+ * (pin_to_offset and offset_to_pin) are required to be called.
+ */
+#define PTO_ENB_REG            0x001
+#define PTO_WDATA_REG          0x002
+#define PTO_DIR_REG            0x004
+#define PTO_IE_REG             0x008
+#define PTO_RDATA_REG          0x010
+#define PTO_MIS_REG            0x020
+
+struct plgpio_regs {
+       u32 enb;                /* enable register */
+       u32 wdata;              /* write data register */
+       u32 dir;                /* direction set register */
+       u32 rdata;              /* read data register */
+       u32 ie;                 /* interrupt enable register */
+       u32 mis;                /* mask interrupt status register */
+       u32 eit;                /* edge interrupt type */
+};
+
+/*
+ * struct plgpio: plgpio driver specific structure
+ *
+ * lock: lock for guarding gpio registers
+ * base: base address of plgpio block
+ * irq_base: irq number of plgpio0
+ * chip: gpio framework specific chip information structure
+ * p2o: function ptr for pin to offset conversion. This is required only for
+ *     machines where mapping b/w pin and offset is not 1-to-1.
+ * o2p: function ptr for offset to pin conversion. This is required only for
+ *     machines where mapping b/w pin and offset is not 1-to-1.
+ * p2o_regs: mask of registers for which p2o and o2p are applicable
+ * regs: register offsets
+ * csave_regs: context save registers for standby/sleep/hibernate cases
+ */
+struct plgpio {
+       spinlock_t              lock;
+       void __iomem            *base;
+       struct clk              *clk;
+       unsigned                irq_base;
+       struct irq_domain       *irq_domain;
+       struct gpio_chip        chip;
+       int                     (*p2o)(int pin);        /* pin_to_offset */
+       int                     (*o2p)(int offset);     /* offset_to_pin */
+       u32                     p2o_regs;
+       struct plgpio_regs      regs;
+#ifdef CONFIG_PM
+       struct plgpio_regs      *csave_regs;
+#endif
+};
+
+/* register manipulation inline functions */
+static inline u32 is_plgpio_set(void __iomem *base, u32 pin, u32 reg)
+{
+       u32 offset = PIN_OFFSET(pin);
+       void __iomem *reg_off = REG_OFFSET(base, reg, pin);
+       u32 val = readl_relaxed(reg_off);
+
+       return !!(val & (1 << offset));
+}
+
+static inline void plgpio_reg_set(void __iomem *base, u32 pin, u32 reg)
+{
+       u32 offset = PIN_OFFSET(pin);
+       void __iomem *reg_off = REG_OFFSET(base, reg, pin);
+       u32 val = readl_relaxed(reg_off);
+
+       writel_relaxed(val | (1 << offset), reg_off);
+}
+
+static inline void plgpio_reg_reset(void __iomem *base, u32 pin, u32 reg)
+{
+       u32 offset = PIN_OFFSET(pin);
+       void __iomem *reg_off = REG_OFFSET(base, reg, pin);
+       u32 val = readl_relaxed(reg_off);
+
+       writel_relaxed(val & ~(1 << offset), reg_off);
+}
+
+/* gpio framework specific routines */
+static int plgpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+       unsigned long flags;
+
+       /* get correct offset for "offset" pin */
+       if (plgpio->p2o && (plgpio->p2o_regs & PTO_DIR_REG)) {
+               offset = plgpio->p2o(offset);
+               if (offset == -1)
+                       return -EINVAL;
+       }
+
+       spin_lock_irqsave(&plgpio->lock, flags);
+       plgpio_reg_set(plgpio->base, offset, plgpio->regs.dir);
+       spin_unlock_irqrestore(&plgpio->lock, flags);
+
+       return 0;
+}
+
+static int plgpio_direction_output(struct gpio_chip *chip, unsigned offset,
+               int value)
+{
+       struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+       unsigned long flags;
+       unsigned dir_offset = offset, wdata_offset = offset, tmp;
+
+       /* get correct offset for "offset" pin */
+       if (plgpio->p2o && (plgpio->p2o_regs & (PTO_DIR_REG | PTO_WDATA_REG))) {
+               tmp = plgpio->p2o(offset);
+               if (tmp == -1)
+                       return -EINVAL;
+
+               if (plgpio->p2o_regs & PTO_DIR_REG)
+                       dir_offset = tmp;
+               if (plgpio->p2o_regs & PTO_WDATA_REG)
+                       wdata_offset = tmp;
+       }
+
+       spin_lock_irqsave(&plgpio->lock, flags);
+       if (value)
+               plgpio_reg_set(plgpio->base, wdata_offset,
+                               plgpio->regs.wdata);
+       else
+               plgpio_reg_reset(plgpio->base, wdata_offset,
+                               plgpio->regs.wdata);
+
+       plgpio_reg_reset(plgpio->base, dir_offset, plgpio->regs.dir);
+       spin_unlock_irqrestore(&plgpio->lock, flags);
+
+       return 0;
+}
+
+static int plgpio_get_value(struct gpio_chip *chip, unsigned offset)
+{
+       struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+
+       if (offset >= chip->ngpio)
+               return -EINVAL;
+
+       /* get correct offset for "offset" pin */
+       if (plgpio->p2o && (plgpio->p2o_regs & PTO_RDATA_REG)) {
+               offset = plgpio->p2o(offset);
+               if (offset == -1)
+                       return -EINVAL;
+       }
+
+       return is_plgpio_set(plgpio->base, offset, plgpio->regs.rdata);
+}
+
+static void plgpio_set_value(struct gpio_chip *chip, unsigned offset, int value)
+{
+       struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+
+       if (offset >= chip->ngpio)
+               return;
+
+       /* get correct offset for "offset" pin */
+       if (plgpio->p2o && (plgpio->p2o_regs & PTO_WDATA_REG)) {
+               offset = plgpio->p2o(offset);
+               if (offset == -1)
+                       return;
+       }
+
+       if (value)
+               plgpio_reg_set(plgpio->base, offset, plgpio->regs.wdata);
+       else
+               plgpio_reg_reset(plgpio->base, offset, plgpio->regs.wdata);
+}
+
+static int plgpio_request(struct gpio_chip *chip, unsigned offset)
+{
+       struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+       int gpio = chip->base + offset;
+       unsigned long flags;
+       int ret = 0;
+
+       if (offset >= chip->ngpio)
+               return -EINVAL;
+
+       ret = pinctrl_request_gpio(gpio);
+       if (ret)
+               return ret;
+
+       if (!IS_ERR(plgpio->clk)) {
+               ret = clk_enable(plgpio->clk);
+               if (ret)
+                       goto err0;
+       }
+
+       if (plgpio->regs.enb == -1)
+               return 0;
+
+       /*
+        * put gpio in IN mode before enabling it. This make enabling gpio safe
+        */
+       ret = plgpio_direction_input(chip, offset);
+       if (ret)
+               goto err1;
+
+       /* get correct offset for "offset" pin */
+       if (plgpio->p2o && (plgpio->p2o_regs & PTO_ENB_REG)) {
+               offset = plgpio->p2o(offset);
+               if (offset == -1) {
+                       ret = -EINVAL;
+                       goto err1;
+               }
+       }
+
+       spin_lock_irqsave(&plgpio->lock, flags);
+       plgpio_reg_set(plgpio->base, offset, plgpio->regs.enb);
+       spin_unlock_irqrestore(&plgpio->lock, flags);
+       return 0;
+
+err1:
+       if (!IS_ERR(plgpio->clk))
+               clk_disable(plgpio->clk);
+err0:
+       pinctrl_free_gpio(gpio);
+       return ret;
+}
+
+static void plgpio_free(struct gpio_chip *chip, unsigned offset)
+{
+       struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+       int gpio = chip->base + offset;
+       unsigned long flags;
+
+       if (offset >= chip->ngpio)
+               return;
+
+       if (plgpio->regs.enb == -1)
+               goto disable_clk;
+
+       /* get correct offset for "offset" pin */
+       if (plgpio->p2o && (plgpio->p2o_regs & PTO_ENB_REG)) {
+               offset = plgpio->p2o(offset);
+               if (offset == -1)
+                       return;
+       }
+
+       spin_lock_irqsave(&plgpio->lock, flags);
+       plgpio_reg_reset(plgpio->base, offset, plgpio->regs.enb);
+       spin_unlock_irqrestore(&plgpio->lock, flags);
+
+disable_clk:
+       if (!IS_ERR(plgpio->clk))
+               clk_disable(plgpio->clk);
+
+       pinctrl_free_gpio(gpio);
+}
+
+static int plgpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+
+       if (IS_ERR_VALUE(plgpio->irq_base))
+               return -EINVAL;
+
+       return irq_find_mapping(plgpio->irq_domain, offset);
+}
+
+/* PLGPIO IRQ */
+static void plgpio_irq_disable(struct irq_data *d)
+{
+       struct plgpio *plgpio = irq_data_get_irq_chip_data(d);
+       int offset = d->irq - plgpio->irq_base;
+       unsigned long flags;
+
+       /* get correct offset for "offset" pin */
+       if (plgpio->p2o && (plgpio->p2o_regs & PTO_IE_REG)) {
+               offset = plgpio->p2o(offset);
+               if (offset == -1)
+                       return;
+       }
+
+       spin_lock_irqsave(&plgpio->lock, flags);
+       plgpio_reg_set(plgpio->base, offset, plgpio->regs.ie);
+       spin_unlock_irqrestore(&plgpio->lock, flags);
+}
+
+static void plgpio_irq_enable(struct irq_data *d)
+{
+       struct plgpio *plgpio = irq_data_get_irq_chip_data(d);
+       int offset = d->irq - plgpio->irq_base;
+       unsigned long flags;
+
+       /* get correct offset for "offset" pin */
+       if (plgpio->p2o && (plgpio->p2o_regs & PTO_IE_REG)) {
+               offset = plgpio->p2o(offset);
+               if (offset == -1)
+                       return;
+       }
+
+       spin_lock_irqsave(&plgpio->lock, flags);
+       plgpio_reg_reset(plgpio->base, offset, plgpio->regs.ie);
+       spin_unlock_irqrestore(&plgpio->lock, flags);
+}
+
+static int plgpio_irq_set_type(struct irq_data *d, unsigned trigger)
+{
+       struct plgpio *plgpio = irq_data_get_irq_chip_data(d);
+       int offset = d->irq - plgpio->irq_base;
+       void __iomem *reg_off;
+       unsigned int supported_type = 0, val;
+
+       if (offset >= plgpio->chip.ngpio)
+               return -EINVAL;
+
+       if (plgpio->regs.eit == -1)
+               supported_type = IRQ_TYPE_LEVEL_HIGH;
+       else
+               supported_type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+
+       if (!(trigger & supported_type))
+               return -EINVAL;
+
+       if (plgpio->regs.eit == -1)
+               return 0;
+
+       reg_off = REG_OFFSET(plgpio->base, plgpio->regs.eit, offset);
+       val = readl_relaxed(reg_off);
+
+       offset = PIN_OFFSET(offset);
+       if (trigger & IRQ_TYPE_EDGE_RISING)
+               writel_relaxed(val | (1 << offset), reg_off);
+       else
+               writel_relaxed(val & ~(1 << offset), reg_off);
+
+       return 0;
+}
+
+static struct irq_chip plgpio_irqchip = {
+       .name           = "PLGPIO",
+       .irq_enable     = plgpio_irq_enable,
+       .irq_disable    = plgpio_irq_disable,
+       .irq_set_type   = plgpio_irq_set_type,
+};
+
+static void plgpio_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+       struct plgpio *plgpio = irq_get_handler_data(irq);
+       struct irq_chip *irqchip = irq_desc_get_chip(desc);
+       int regs_count, count, pin, offset, i = 0;
+       unsigned long pending;
+
+       count = plgpio->chip.ngpio;
+       regs_count = DIV_ROUND_UP(count, MAX_GPIO_PER_REG);
+
+       chained_irq_enter(irqchip, desc);
+       /* check all plgpio MIS registers for a possible interrupt */
+       for (; i < regs_count; i++) {
+               pending = readl_relaxed(plgpio->base + plgpio->regs.mis +
+                               i * sizeof(int *));
+               if (!pending)
+                       continue;
+
+               /* clear interrupts */
+               writel_relaxed(~pending, plgpio->base + plgpio->regs.mis +
+                               i * sizeof(int *));
+               /*
+                * clear extra bits in last register having gpios < MAX/REG
+                * ex: Suppose there are max 102 plgpios. then last register
+                * must have only (102 - MAX_GPIO_PER_REG * 3) = 6 relevant bits
+                * so, we must not take other 28 bits into consideration for
+                * checking interrupt. so clear those bits.
+                */
+               count = count - i * MAX_GPIO_PER_REG;
+               if (count < MAX_GPIO_PER_REG)
+                       pending &= (1 << count) - 1;
+
+               for_each_set_bit(offset, &pending, MAX_GPIO_PER_REG) {
+                       /* get correct pin for "offset" */
+                       if (plgpio->o2p && (plgpio->p2o_regs & PTO_MIS_REG)) {
+                               pin = plgpio->o2p(offset);
+                               if (pin == -1)
+                                       continue;
+                       } else
+                               pin = offset;
+
+                       /* get correct irq line number */
+                       pin = i * MAX_GPIO_PER_REG + pin;
+                       generic_handle_irq(plgpio_to_irq(&plgpio->chip, pin));
+               }
+       }
+       chained_irq_exit(irqchip, desc);
+}
+
+/*
+ * pin to offset and offset to pin converter functions
+ *
+ * In spear310 there is inconsistency among bit positions in plgpio regiseters,
+ * for different plgpio pins. For example: for pin 27, bit offset is 23, pin
+ * 28-33 are not supported, pin 95 has offset bit 95, bit 100 has offset bit 1
+ */
+static int spear310_p2o(int pin)
+{
+       int offset = pin;
+
+       if (pin <= 27)
+               offset += 4;
+       else if (pin <= 33)
+               offset = -1;
+       else if (pin <= 97)
+               offset -= 2;
+       else if (pin <= 101)
+               offset = 101 - pin;
+       else
+               offset = -1;
+
+       return offset;
+}
+
+int spear310_o2p(int offset)
+{
+       if (offset <= 3)
+               return 101 - offset;
+       else if (offset <= 31)
+               return offset - 4;
+       else
+               return offset + 2;
+}
+
+static int __devinit plgpio_probe_dt(struct platform_device *pdev,
+               struct plgpio *plgpio)
+{
+       struct device_node *np = pdev->dev.of_node;
+       int ret = -EINVAL;
+       u32 val;
+
+       if (of_machine_is_compatible("st,spear310")) {
+               plgpio->p2o = spear310_p2o;
+               plgpio->o2p = spear310_o2p;
+               plgpio->p2o_regs = PTO_WDATA_REG | PTO_DIR_REG | PTO_IE_REG |
+                       PTO_RDATA_REG | PTO_MIS_REG;
+       }
+
+       if (!of_property_read_u32(np, "st-plgpio,ngpio", &val)) {
+               plgpio->chip.ngpio = val;
+       } else {
+               dev_err(&pdev->dev, "DT: Invalid ngpio field\n");
+               goto end;
+       }
+
+       if (!of_property_read_u32(np, "st-plgpio,enb-reg", &val))
+               plgpio->regs.enb = val;
+       else
+               plgpio->regs.enb = -1;
+
+       if (!of_property_read_u32(np, "st-plgpio,wdata-reg", &val)) {
+               plgpio->regs.wdata = val;
+       } else {
+               dev_err(&pdev->dev, "DT: Invalid wdata reg\n");
+               goto end;
+       }
+
+       if (!of_property_read_u32(np, "st-plgpio,dir-reg", &val)) {
+               plgpio->regs.dir = val;
+       } else {
+               dev_err(&pdev->dev, "DT: Invalid dir reg\n");
+               goto end;
+       }
+
+       if (!of_property_read_u32(np, "st-plgpio,ie-reg", &val)) {
+               plgpio->regs.ie = val;
+       } else {
+               dev_err(&pdev->dev, "DT: Invalid ie reg\n");
+               goto end;
+       }
+
+       if (!of_property_read_u32(np, "st-plgpio,rdata-reg", &val)) {
+               plgpio->regs.rdata = val;
+       } else {
+               dev_err(&pdev->dev, "DT: Invalid rdata reg\n");
+               goto end;
+       }
+
+       if (!of_property_read_u32(np, "st-plgpio,mis-reg", &val)) {
+               plgpio->regs.mis = val;
+       } else {
+               dev_err(&pdev->dev, "DT: Invalid mis reg\n");
+               goto end;
+       }
+
+       if (!of_property_read_u32(np, "st-plgpio,eit-reg", &val))
+               plgpio->regs.eit = val;
+       else
+               plgpio->regs.eit = -1;
+
+       return 0;
+
+end:
+       return ret;
+}
+static int __devinit plgpio_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct plgpio *plgpio;
+       struct resource *res;
+       int ret, irq, i;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "invalid IORESOURCE_MEM\n");
+               return -EBUSY;
+       }
+
+       plgpio = devm_kzalloc(&pdev->dev, sizeof(*plgpio), GFP_KERNEL);
+       if (!plgpio) {
+               dev_err(&pdev->dev, "memory allocation fail\n");
+               return -ENOMEM;
+       }
+
+       plgpio->base = devm_request_and_ioremap(&pdev->dev, res);
+       if (!plgpio->base) {
+               dev_err(&pdev->dev, "request and ioremap fail\n");
+               return -ENOMEM;
+       }
+
+       ret = plgpio_probe_dt(pdev, plgpio);
+       if (ret) {
+               dev_err(&pdev->dev, "DT probe failed\n");
+               return ret;
+       }
+
+       plgpio->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(plgpio->clk))
+               dev_warn(&pdev->dev, "clk_get() failed, work without it\n");
+
+#ifdef CONFIG_PM
+       plgpio->csave_regs = devm_kzalloc(&pdev->dev,
+                       sizeof(*plgpio->csave_regs) *
+                       DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG),
+                       GFP_KERNEL);
+       if (!plgpio->csave_regs) {
+               dev_err(&pdev->dev, "csave registers memory allocation fail\n");
+               return -ENOMEM;
+       }
+#endif
+
+       platform_set_drvdata(pdev, plgpio);
+       spin_lock_init(&plgpio->lock);
+
+       plgpio->irq_base = -1;
+       plgpio->chip.base = -1;
+       plgpio->chip.request = plgpio_request;
+       plgpio->chip.free = plgpio_free;
+       plgpio->chip.direction_input = plgpio_direction_input;
+       plgpio->chip.direction_output = plgpio_direction_output;
+       plgpio->chip.get = plgpio_get_value;
+       plgpio->chip.set = plgpio_set_value;
+       plgpio->chip.to_irq = plgpio_to_irq;
+       plgpio->chip.label = dev_name(&pdev->dev);
+       plgpio->chip.dev = &pdev->dev;
+       plgpio->chip.owner = THIS_MODULE;
+
+       if (!IS_ERR(plgpio->clk)) {
+               ret = clk_prepare(plgpio->clk);
+               if (ret) {
+                       dev_err(&pdev->dev, "clk prepare failed\n");
+                       return ret;
+               }
+       }
+
+       ret = gpiochip_add(&plgpio->chip);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to add gpio chip\n");
+               goto unprepare_clk;
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_info(&pdev->dev, "irqs not supported\n");
+               return 0;
+       }
+
+       plgpio->irq_base = irq_alloc_descs(-1, 0, plgpio->chip.ngpio, 0);
+       if (IS_ERR_VALUE(plgpio->irq_base)) {
+               /* we would not support irq for gpio */
+               dev_warn(&pdev->dev, "couldn't allocate irq base\n");
+               return 0;
+       }
+
+       plgpio->irq_domain = irq_domain_add_legacy(np, plgpio->chip.ngpio,
+                       plgpio->irq_base, 0, &irq_domain_simple_ops, NULL);
+       if (WARN_ON(!plgpio->irq_domain)) {
+               dev_err(&pdev->dev, "irq domain init failed\n");
+               irq_free_descs(plgpio->irq_base, plgpio->chip.ngpio);
+               ret = -ENXIO;
+               goto remove_gpiochip;
+       }
+
+       irq_set_chained_handler(irq, plgpio_irq_handler);
+       for (i = 0; i < plgpio->chip.ngpio; i++) {
+               irq_set_chip_and_handler(i + plgpio->irq_base, &plgpio_irqchip,
+                               handle_simple_irq);
+               set_irq_flags(i + plgpio->irq_base, IRQF_VALID);
+               irq_set_chip_data(i + plgpio->irq_base, plgpio);
+       }
+
+       irq_set_handler_data(irq, plgpio);
+       dev_info(&pdev->dev, "PLGPIO registered with IRQs\n");
+
+       return 0;
+
+remove_gpiochip:
+       dev_info(&pdev->dev, "Remove gpiochip\n");
+       if (gpiochip_remove(&plgpio->chip))
+               dev_err(&pdev->dev, "unable to remove gpiochip\n");
+unprepare_clk:
+       if (!IS_ERR(plgpio->clk))
+               clk_unprepare(plgpio->clk);
+
+       return ret;
+}
+
+#ifdef CONFIG_PM
+static int plgpio_suspend(struct device *dev)
+{
+       struct plgpio *plgpio = dev_get_drvdata(dev);
+       int i, reg_count = DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG);
+       void __iomem *off;
+
+       for (i = 0; i < reg_count; i++) {
+               off = plgpio->base + i * sizeof(int *);
+
+               if (plgpio->regs.enb != -1)
+                       plgpio->csave_regs[i].enb =
+                               readl_relaxed(plgpio->regs.enb + off);
+               if (plgpio->regs.eit != -1)
+                       plgpio->csave_regs[i].eit =
+                               readl_relaxed(plgpio->regs.eit + off);
+               plgpio->csave_regs[i].wdata = readl_relaxed(plgpio->regs.wdata +
+                               off);
+               plgpio->csave_regs[i].dir = readl_relaxed(plgpio->regs.dir +
+                               off);
+               plgpio->csave_regs[i].ie = readl_relaxed(plgpio->regs.ie + off);
+       }
+
+       return 0;
+}
+
+/*
+ * This is used to correct the values in end registers. End registers contain
+ * extra bits that might be used for other purpose in platform. So, we shouldn't
+ * overwrite these bits. This macro, reads given register again, preserves other
+ * bit values (non-plgpio bits), and retain captured value (plgpio bits).
+ */
+#define plgpio_prepare_reg(__reg, _off, _mask, _tmp)           \
+{                                                              \
+       _tmp = readl_relaxed(plgpio->regs.__reg + _off);                \
+       _tmp &= ~_mask;                                         \
+       plgpio->csave_regs[i].__reg =                           \
+               _tmp | (plgpio->csave_regs[i].__reg & _mask);   \
+}
+
+static int plgpio_resume(struct device *dev)
+{
+       struct plgpio *plgpio = dev_get_drvdata(dev);
+       int i, reg_count = DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG);
+       void __iomem *off;
+       u32 mask, tmp;
+
+       for (i = 0; i < reg_count; i++) {
+               off = plgpio->base + i * sizeof(int *);
+
+               if (i == reg_count - 1) {
+                       mask = (1 << (plgpio->chip.ngpio - i *
+                                               MAX_GPIO_PER_REG)) - 1;
+
+                       if (plgpio->regs.enb != -1)
+                               plgpio_prepare_reg(enb, off, mask, tmp);
+
+                       if (plgpio->regs.eit != -1)
+                               plgpio_prepare_reg(eit, off, mask, tmp);
+
+                       plgpio_prepare_reg(wdata, off, mask, tmp);
+                       plgpio_prepare_reg(dir, off, mask, tmp);
+                       plgpio_prepare_reg(ie, off, mask, tmp);
+               }
+
+               writel_relaxed(plgpio->csave_regs[i].wdata, plgpio->regs.wdata +
+                               off);
+               writel_relaxed(plgpio->csave_regs[i].dir, plgpio->regs.dir +
+                               off);
+
+               if (plgpio->regs.eit != -1)
+                       writel_relaxed(plgpio->csave_regs[i].eit,
+                                       plgpio->regs.eit + off);
+
+               writel_relaxed(plgpio->csave_regs[i].ie, plgpio->regs.ie + off);
+
+               if (plgpio->regs.enb != -1)
+                       writel_relaxed(plgpio->csave_regs[i].enb,
+                                       plgpio->regs.enb + off);
+       }
+
+       return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(plgpio_dev_pm_ops, plgpio_suspend, plgpio_resume);
+
+static const struct of_device_id plgpio_of_match[] = {
+       { .compatible = "st,spear-plgpio" },
+       {}
+};
+MODULE_DEVICE_TABLE(of, plgpio_of_match);
+
+static struct platform_driver plgpio_driver = {
+       .probe = plgpio_probe,
+       .driver = {
+               .owner = THIS_MODULE,
+               .name = "spear-plgpio",
+               .pm = &plgpio_dev_pm_ops,
+               .of_match_table = of_match_ptr(plgpio_of_match),
+       },
+};
+
+static int __init plgpio_init(void)
+{
+       return platform_driver_register(&plgpio_driver);
+}
+subsys_initcall(plgpio_init);
+
+MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
+MODULE_DESCRIPTION("ST Microlectronics SPEAr PLGPIO driver");
+MODULE_LICENSE("GPL");
index 5d4f44f..bf78eb7 100644 (file)
  */
 
 #include <linux/err.h>
-#include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_gpio.h>
 #include <linux/pinctrl/machine.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinmux.h>
 
 #define DRIVER_NAME "spear-pinmux"
 
-static inline u32 pmx_readl(struct spear_pmx *pmx, u32 reg)
+static void muxregs_endisable(struct spear_pmx *pmx,
+               struct spear_muxreg *muxregs, u8 count, bool enable)
 {
-       return readl_relaxed(pmx->vbase + reg);
-}
+       struct spear_muxreg *muxreg;
+       u32 val, temp, j;
 
-static inline void pmx_writel(struct spear_pmx *pmx, u32 val, u32 reg)
-{
-       writel_relaxed(val, pmx->vbase + reg);
+       for (j = 0; j < count; j++) {
+               muxreg = &muxregs[j];
+
+               val = pmx_readl(pmx, muxreg->reg);
+               val &= ~muxreg->mask;
+
+               if (enable)
+                       temp = muxreg->val;
+               else
+                       temp = ~muxreg->val;
+
+               val |= muxreg->mask & temp;
+               pmx_writel(pmx, val, muxreg->reg);
+       }
 }
 
 static int set_mode(struct spear_pmx *pmx, int mode)
@@ -70,6 +82,17 @@ static int set_mode(struct spear_pmx *pmx, int mode)
        return 0;
 }
 
+void __devinit
+pmx_init_gpio_pingroup_addr(struct spear_gpio_pingroup *gpio_pingroup,
+               unsigned count, u16 reg)
+{
+       int i, j;
+
+       for (i = 0; i < count; i++)
+               for (j = 0; j < gpio_pingroup[i].nmuxregs; j++)
+                       gpio_pingroup[i].muxregs[j].reg = reg;
+}
+
 void __devinit pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg)
 {
        struct spear_pingroup *pgroup;
@@ -121,9 +144,10 @@ static void spear_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
        seq_printf(s, " " DRIVER_NAME);
 }
 
-int spear_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
-                                struct device_node *np_config,
-                                struct pinctrl_map **map, unsigned *num_maps)
+static int spear_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+                                       struct device_node *np_config,
+                                       struct pinctrl_map **map,
+                                       unsigned *num_maps)
 {
        struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
        struct device_node *np;
@@ -168,8 +192,9 @@ int spear_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
        return 0;
 }
 
-void spear_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
-               struct pinctrl_map *map, unsigned num_maps)
+static void spear_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
+                                     struct pinctrl_map *map,
+                                     unsigned num_maps)
 {
        kfree(map);
 }
@@ -216,9 +241,7 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev,
        struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
        const struct spear_pingroup *pgroup;
        const struct spear_modemux *modemux;
-       struct spear_muxreg *muxreg;
-       u32 val, temp;
-       int i, j;
+       int i;
        bool found = false;
 
        pgroup = pmx->machdata->groups[group];
@@ -233,20 +256,8 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev,
                }
 
                found = true;
-               for (j = 0; j < modemux->nmuxregs; j++) {
-                       muxreg = &modemux->muxregs[j];
-
-                       val = pmx_readl(pmx, muxreg->reg);
-                       val &= ~muxreg->mask;
-
-                       if (enable)
-                               temp = muxreg->val;
-                       else
-                               temp = ~muxreg->val;
-
-                       val |= temp;
-                       pmx_writel(pmx, val, muxreg->reg);
-               }
+               muxregs_endisable(pmx, modemux->muxregs, modemux->nmuxregs,
+                               enable);
        }
 
        if (!found) {
@@ -270,12 +281,74 @@ static void spear_pinctrl_disable(struct pinctrl_dev *pctldev,
        spear_pinctrl_endisable(pctldev, function, group, false);
 }
 
+/* gpio with pinmux */
+static struct spear_gpio_pingroup *get_gpio_pingroup(struct spear_pmx *pmx,
+               unsigned pin)
+{
+       struct spear_gpio_pingroup *gpio_pingroup;
+       int i, j;
+
+       if (!pmx->machdata->gpio_pingroups)
+               return NULL;
+
+       for (i = 0; i < pmx->machdata->ngpio_pingroups; i++) {
+               gpio_pingroup = &pmx->machdata->gpio_pingroups[i];
+
+               for (j = 0; j < gpio_pingroup->npins; j++) {
+                       if (gpio_pingroup->pins[j] == pin)
+                               return gpio_pingroup;
+               }
+       }
+
+       return NULL;
+}
+
+static int gpio_request_endisable(struct pinctrl_dev *pctldev,
+               struct pinctrl_gpio_range *range, unsigned offset, bool enable)
+{
+       struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+       struct spear_pinctrl_machdata *machdata = pmx->machdata;
+       struct spear_gpio_pingroup *gpio_pingroup;
+
+       /*
+        * Some SoC have configuration options applicable to group of pins,
+        * rather than a single pin.
+        */
+       gpio_pingroup = get_gpio_pingroup(pmx, offset);
+       if (gpio_pingroup)
+               muxregs_endisable(pmx, gpio_pingroup->muxregs,
+                               gpio_pingroup->nmuxregs, enable);
+
+       /*
+        * SoC may need some extra configurations, or configurations for single
+        * pin
+        */
+       if (machdata->gpio_request_endisable)
+               machdata->gpio_request_endisable(pmx, offset, enable);
+
+       return 0;
+}
+
+static int gpio_request_enable(struct pinctrl_dev *pctldev,
+               struct pinctrl_gpio_range *range, unsigned offset)
+{
+       return gpio_request_endisable(pctldev, range, offset, true);
+}
+
+static void gpio_disable_free(struct pinctrl_dev *pctldev,
+               struct pinctrl_gpio_range *range, unsigned offset)
+{
+       gpio_request_endisable(pctldev, range, offset, false);
+}
+
 static struct pinmux_ops spear_pinmux_ops = {
        .get_functions_count = spear_pinctrl_get_funcs_count,
        .get_function_name = spear_pinctrl_get_func_name,
        .get_function_groups = spear_pinctrl_get_func_groups,
        .enable = spear_pinctrl_enable,
        .disable = spear_pinctrl_disable,
+       .gpio_request_enable = gpio_request_enable,
+       .gpio_disable_free = gpio_disable_free,
 };
 
 static struct pinctrl_desc spear_pinctrl_desc = {
index d950eb7..b063327 100644 (file)
 #ifndef __PINMUX_SPEAR_H__
 #define __PINMUX_SPEAR_H__
 
+#include <linux/gpio.h>
+#include <linux/io.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/types.h>
 
 struct platform_device;
 struct device;
+struct spear_pmx;
 
 /**
  * struct spear_pmx_mode - SPEAr pmx mode
@@ -46,6 +49,44 @@ struct spear_muxreg {
        u32 val;
 };
 
+struct spear_gpio_pingroup {
+       const unsigned *pins;
+       unsigned npins;
+       struct spear_muxreg *muxregs;
+       u8 nmuxregs;
+};
+
+/* ste: set to enable */
+#define DEFINE_MUXREG(__pins, __muxreg, __mask, __ste)         \
+static struct spear_muxreg __pins##_muxregs[] = {              \
+       {                                                       \
+               .reg = __muxreg,                                \
+               .mask = __mask,                                 \
+               .val = __ste ? __mask : 0,                      \
+       },                                                      \
+}
+
+#define DEFINE_2_MUXREG(__pins, __muxreg1, __muxreg2, __mask, __ste1, __ste2) \
+static struct spear_muxreg __pins##_muxregs[] = {              \
+       {                                                       \
+               .reg = __muxreg1,                               \
+               .mask = __mask,                                 \
+               .val = __ste1 ? __mask : 0,                     \
+       }, {                                                    \
+               .reg = __muxreg2,                               \
+               .mask = __mask,                                 \
+               .val = __ste2 ? __mask : 0,                     \
+       },                                                      \
+}
+
+#define GPIO_PINGROUP(__pins)                                  \
+       {                                                       \
+               .pins = __pins,                                 \
+               .npins = ARRAY_SIZE(__pins),                    \
+               .muxregs = __pins##_muxregs,                    \
+               .nmuxregs = ARRAY_SIZE(__pins##_muxregs),       \
+       }
+
 /**
  * struct spear_modemux - SPEAr mode mux configuration
  * @modes: mode ids supported by this group of muxregs
@@ -100,6 +141,8 @@ struct spear_function {
  * @nfunctions: The numbmer of entries in @functions.
  * @groups: An array describing all pin groups the pin SoC supports.
  * @ngroups: The numbmer of entries in @groups.
+ * @gpio_pingroups: gpio pingroups
+ * @ngpio_pingroups: gpio pingroups count
  *
  * @modes_supported: Does SoC support modes
  * @mode: mode configured from probe
@@ -113,6 +156,10 @@ struct spear_pinctrl_machdata {
        unsigned nfunctions;
        struct spear_pingroup **groups;
        unsigned ngroups;
+       struct spear_gpio_pingroup *gpio_pingroups;
+       void (*gpio_request_endisable)(struct spear_pmx *pmx, int offset,
+                       bool enable);
+       unsigned ngpio_pingroups;
 
        bool modes_supported;
        u16 mode;
@@ -135,7 +182,20 @@ struct spear_pmx {
 };
 
 /* exported routines */
+static inline u32 pmx_readl(struct spear_pmx *pmx, u32 reg)
+{
+       return readl_relaxed(pmx->vbase + reg);
+}
+
+static inline void pmx_writel(struct spear_pmx *pmx, u32 val, u32 reg)
+{
+       writel_relaxed(val, pmx->vbase + reg);
+}
+
 void __devinit pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg);
+void __devinit
+pmx_init_gpio_pingroup_addr(struct spear_gpio_pingroup *gpio_pingroup,
+               unsigned count, u16 reg);
 int __devinit spear_pinctrl_probe(struct platform_device *pdev,
                struct spear_pinctrl_machdata *machdata);
 int __devexit spear_pinctrl_remove(struct platform_device *pdev);
index d6cca8c..30134f7 100644 (file)
@@ -25,8 +25,8 @@ static const struct pinctrl_pin_desc spear1310_pins[] = {
 };
 
 /* registers */
-#define PERIP_CFG                                      0x32C
-       #define MCIF_SEL_SHIFT                          3
+#define PERIP_CFG                                      0x3B0
+       #define MCIF_SEL_SHIFT                          5
        #define MCIF_SEL_SD                             (0x1 << MCIF_SEL_SHIFT)
        #define MCIF_SEL_CF                             (0x2 << MCIF_SEL_SHIFT)
        #define MCIF_SEL_XD                             (0x3 << MCIF_SEL_SHIFT)
@@ -164,6 +164,10 @@ static const struct pinctrl_pin_desc spear1310_pins[] = {
        #define PMX_SSP0_CS0_MASK                       (1 << 29)
        #define PMX_SSP0_CS1_2_MASK                     (1 << 30)
 
+#define PAD_DIRECTION_SEL_0                            0x65C
+#define PAD_DIRECTION_SEL_1                            0x660
+#define PAD_DIRECTION_SEL_2                            0x664
+
 /* combined macros */
 #define PMX_GMII_MASK          (PMX_GMIICLK_MASK |                     \
                                PMX_GMIICOL_CRS_XFERER_MIITXCLK_MASK |  \
@@ -237,6 +241,10 @@ static struct spear_muxreg i2c0_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_I2C0_MASK,
                .val = PMX_I2C0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_I2C0_MASK,
+               .val = PMX_I2C0_MASK,
        },
 };
 
@@ -269,6 +277,10 @@ static struct spear_muxreg ssp0_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_SSP0_MASK,
                .val = PMX_SSP0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_SSP0_MASK,
+               .val = PMX_SSP0_MASK,
        },
 };
 
@@ -294,6 +306,10 @@ static struct spear_muxreg ssp0_cs0_muxreg[] = {
                .reg = PAD_FUNCTION_EN_2,
                .mask = PMX_SSP0_CS0_MASK,
                .val = PMX_SSP0_CS0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_SSP0_CS0_MASK,
+               .val = PMX_SSP0_CS0_MASK,
        },
 };
 
@@ -319,6 +335,10 @@ static struct spear_muxreg ssp0_cs1_2_muxreg[] = {
                .reg = PAD_FUNCTION_EN_2,
                .mask = PMX_SSP0_CS1_2_MASK,
                .val = PMX_SSP0_CS1_2_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_SSP0_CS1_2_MASK,
+               .val = PMX_SSP0_CS1_2_MASK,
        },
 };
 
@@ -352,6 +372,10 @@ static struct spear_muxreg i2s0_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_I2S0_MASK,
                .val = PMX_I2S0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_I2S0_MASK,
+               .val = PMX_I2S0_MASK,
        },
 };
 
@@ -384,6 +408,10 @@ static struct spear_muxreg i2s1_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_I2S1_MASK,
                .val = PMX_I2S1_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_I2S1_MASK,
+               .val = PMX_I2S1_MASK,
        },
 };
 
@@ -418,6 +446,10 @@ static struct spear_muxreg clcd_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_CLCD1_MASK,
                .val = PMX_CLCD1_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_CLCD1_MASK,
+               .val = PMX_CLCD1_MASK,
        },
 };
 
@@ -443,6 +475,10 @@ static struct spear_muxreg clcd_high_res_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_CLCD2_MASK,
                .val = PMX_CLCD2_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_CLCD2_MASK,
+               .val = PMX_CLCD2_MASK,
        },
 };
 
@@ -461,7 +497,7 @@ static struct spear_pingroup clcd_high_res_pingroup = {
        .nmodemuxs = ARRAY_SIZE(clcd_high_res_modemux),
 };
 
-static const char *const clcd_grps[] = { "clcd_grp", "clcd_high_res" };
+static const char *const clcd_grps[] = { "clcd_grp", "clcd_high_res_grp" };
 static struct spear_function clcd_function = {
        .name = "clcd",
        .groups = clcd_grps,
@@ -479,6 +515,14 @@ static struct spear_muxreg arm_gpio_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_EGPIO_1_GRP_MASK,
                .val = PMX_EGPIO_1_GRP_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_EGPIO_0_GRP_MASK,
+               .val = PMX_EGPIO_0_GRP_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_EGPIO_1_GRP_MASK,
+               .val = PMX_EGPIO_1_GRP_MASK,
        },
 };
 
@@ -511,6 +555,10 @@ static struct spear_muxreg smi_2_chips_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_SMI_MASK,
                .val = PMX_SMI_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_SMI_MASK,
+               .val = PMX_SMI_MASK,
        },
 };
 
@@ -539,6 +587,14 @@ static struct spear_muxreg smi_4_chips_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
                .val = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_SMI_MASK,
+               .val = PMX_SMI_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
+               .val = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
        },
 };
 
@@ -573,6 +629,10 @@ static struct spear_muxreg gmii_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_GMII_MASK,
                .val = PMX_GMII_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_GMII_MASK,
+               .val = PMX_GMII_MASK,
        },
 };
 
@@ -615,6 +675,18 @@ static struct spear_muxreg rgmii_muxreg[] = {
                .reg = PAD_FUNCTION_EN_2,
                .mask = PMX_RGMII_REG2_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_RGMII_REG0_MASK,
+               .val = PMX_RGMII_REG0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_RGMII_REG1_MASK,
+               .val = PMX_RGMII_REG1_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_RGMII_REG2_MASK,
+               .val = PMX_RGMII_REG2_MASK,
        },
 };
 
@@ -649,6 +721,10 @@ static struct spear_muxreg smii_0_1_2_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_SMII_0_1_2_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_SMII_0_1_2_MASK,
+               .val = PMX_SMII_0_1_2_MASK,
        },
 };
 
@@ -681,6 +757,10 @@ static struct spear_muxreg ras_mii_txclk_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_NFCE2_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_NFCE2_MASK,
+               .val = PMX_NFCE2_MASK,
        },
 };
 
@@ -721,6 +801,14 @@ static struct spear_muxreg nand_8bit_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_NAND8BIT_1_MASK,
                .val = PMX_NAND8BIT_1_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_NAND8BIT_0_MASK,
+               .val = PMX_NAND8BIT_0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_NAND8BIT_1_MASK,
+               .val = PMX_NAND8BIT_1_MASK,
        },
 };
 
@@ -747,6 +835,10 @@ static struct spear_muxreg nand_16bit_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_NAND16BIT_1_MASK,
                .val = PMX_NAND16BIT_1_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_NAND16BIT_1_MASK,
+               .val = PMX_NAND16BIT_1_MASK,
        },
 };
 
@@ -772,6 +864,10 @@ static struct spear_muxreg nand_4_chips_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_NAND_4CHIPS_MASK,
                .val = PMX_NAND_4CHIPS_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_NAND_4CHIPS_MASK,
+               .val = PMX_NAND_4CHIPS_MASK,
        },
 };
 
@@ -833,6 +929,10 @@ static struct spear_muxreg keyboard_rowcol6_8_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_KBD_ROWCOL68_MASK,
                .val = PMX_KBD_ROWCOL68_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_KBD_ROWCOL68_MASK,
+               .val = PMX_KBD_ROWCOL68_MASK,
        },
 };
 
@@ -866,6 +966,10 @@ static struct spear_muxreg uart0_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_UART0_MASK,
                .val = PMX_UART0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_UART0_MASK,
+               .val = PMX_UART0_MASK,
        },
 };
 
@@ -891,6 +995,10 @@ static struct spear_muxreg uart0_modem_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_UART0_MODEM_MASK,
                .val = PMX_UART0_MODEM_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_UART0_MODEM_MASK,
+               .val = PMX_UART0_MODEM_MASK,
        },
 };
 
@@ -923,6 +1031,10 @@ static struct spear_muxreg gpt0_tmr0_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_GPT0_TMR0_MASK,
                .val = PMX_GPT0_TMR0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_GPT0_TMR0_MASK,
+               .val = PMX_GPT0_TMR0_MASK,
        },
 };
 
@@ -948,6 +1060,10 @@ static struct spear_muxreg gpt0_tmr1_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_GPT0_TMR1_MASK,
                .val = PMX_GPT0_TMR1_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_GPT0_TMR1_MASK,
+               .val = PMX_GPT0_TMR1_MASK,
        },
 };
 
@@ -980,6 +1096,10 @@ static struct spear_muxreg gpt1_tmr0_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_GPT1_TMR0_MASK,
                .val = PMX_GPT1_TMR0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_GPT1_TMR0_MASK,
+               .val = PMX_GPT1_TMR0_MASK,
        },
 };
 
@@ -1005,6 +1125,10 @@ static struct spear_muxreg gpt1_tmr1_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_GPT1_TMR1_MASK,
                .val = PMX_GPT1_TMR1_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_GPT1_TMR1_MASK,
+               .val = PMX_GPT1_TMR1_MASK,
        },
 };
 
@@ -1049,6 +1173,20 @@ static const unsigned mcif_pins[] = { 86, 87, 88, 89, 90, 91, 92, 93, 213, 214,
                .reg = PAD_FUNCTION_EN_2,                       \
                .mask = PMX_MCIFALL_2_MASK,                     \
                .val = PMX_MCIFALL_2_MASK,                      \
+       }, {                                                    \
+               .reg = PAD_DIRECTION_SEL_0,                     \
+               .mask = PMX_MCI_DATA8_15_MASK,                  \
+               .val = PMX_MCI_DATA8_15_MASK,                   \
+       }, {                                                    \
+               .reg = PAD_DIRECTION_SEL_1,                     \
+               .mask = PMX_MCIFALL_1_MASK | PMX_NFWPRT1_MASK | \
+                       PMX_NFWPRT2_MASK,                       \
+               .val = PMX_MCIFALL_1_MASK | PMX_NFWPRT1_MASK |  \
+                       PMX_NFWPRT2_MASK,                       \
+       }, {                                                    \
+               .reg = PAD_DIRECTION_SEL_2,                     \
+               .mask = PMX_MCIFALL_2_MASK,                     \
+               .val = PMX_MCIFALL_2_MASK,                      \
        }
 
 /* sdhci device */
@@ -1154,6 +1292,10 @@ static struct spear_muxreg touch_xy_muxreg[] = {
                .reg = PAD_FUNCTION_EN_2,
                .mask = PMX_TOUCH_XY_MASK,
                .val = PMX_TOUCH_XY_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_TOUCH_XY_MASK,
+               .val = PMX_TOUCH_XY_MASK,
        },
 };
 
@@ -1187,6 +1329,10 @@ static struct spear_muxreg uart1_dis_i2c_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_I2C0_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_I2C0_MASK,
+               .val = PMX_I2C0_MASK,
        },
 };
 
@@ -1213,6 +1359,12 @@ static struct spear_muxreg uart1_dis_sd_muxreg[] = {
                .mask = PMX_MCIDATA1_MASK |
                        PMX_MCIDATA2_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_MCIDATA1_MASK |
+                       PMX_MCIDATA2_MASK,
+               .val = PMX_MCIDATA1_MASK |
+                       PMX_MCIDATA2_MASK,
        },
 };
 
@@ -1246,6 +1398,10 @@ static struct spear_muxreg uart2_3_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_I2S0_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_I2S0_MASK,
+               .val = PMX_I2S0_MASK,
        },
 };
 
@@ -1278,6 +1434,10 @@ static struct spear_muxreg uart4_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_I2S0_MASK | PMX_CLCD1_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_I2S0_MASK | PMX_CLCD1_MASK,
+               .val = PMX_I2S0_MASK | PMX_CLCD1_MASK,
        },
 };
 
@@ -1310,6 +1470,10 @@ static struct spear_muxreg uart5_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_CLCD1_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_CLCD1_MASK,
+               .val = PMX_CLCD1_MASK,
        },
 };
 
@@ -1344,6 +1508,10 @@ static struct spear_muxreg rs485_0_1_tdm_0_1_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_CLCD1_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_CLCD1_MASK,
+               .val = PMX_CLCD1_MASK,
        },
 };
 
@@ -1376,6 +1544,10 @@ static struct spear_muxreg i2c_1_2_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_CLCD1_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_CLCD1_MASK,
+               .val = PMX_CLCD1_MASK,
        },
 };
 
@@ -1409,6 +1581,10 @@ static struct spear_muxreg i2c3_dis_smi_clcd_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_CLCD1_MASK | PMX_SMI_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_CLCD1_MASK | PMX_SMI_MASK,
+               .val = PMX_CLCD1_MASK | PMX_SMI_MASK,
        },
 };
 
@@ -1435,6 +1611,10 @@ static struct spear_muxreg i2c3_dis_sd_i2s0_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_I2S1_MASK | PMX_MCIDATA3_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_I2S1_MASK | PMX_MCIDATA3_MASK,
+               .val = PMX_I2S1_MASK | PMX_MCIDATA3_MASK,
        },
 };
 
@@ -1469,6 +1649,10 @@ static struct spear_muxreg i2c_4_5_dis_smi_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_SMI_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_SMI_MASK,
+               .val = PMX_SMI_MASK,
        },
 };
 
@@ -1499,6 +1683,14 @@ static struct spear_muxreg i2c4_dis_sd_muxreg[] = {
                .reg = PAD_FUNCTION_EN_2,
                .mask = PMX_MCIDATA5_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_MCIDATA4_MASK,
+               .val = PMX_MCIDATA4_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_MCIDATA5_MASK,
+               .val = PMX_MCIDATA5_MASK,
        },
 };
 
@@ -1526,6 +1718,12 @@ static struct spear_muxreg i2c5_dis_sd_muxreg[] = {
                .mask = PMX_MCIDATA6_MASK |
                        PMX_MCIDATA7_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_MCIDATA6_MASK |
+                       PMX_MCIDATA7_MASK,
+               .val = PMX_MCIDATA6_MASK |
+                       PMX_MCIDATA7_MASK,
        },
 };
 
@@ -1560,6 +1758,10 @@ static struct spear_muxreg i2c_6_7_dis_kbd_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_KBD_ROWCOL25_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_KBD_ROWCOL25_MASK,
+               .val = PMX_KBD_ROWCOL25_MASK,
        },
 };
 
@@ -1587,6 +1789,12 @@ static struct spear_muxreg i2c6_dis_sd_muxreg[] = {
                .mask = PMX_MCIIORDRE_MASK |
                        PMX_MCIIOWRWE_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_MCIIORDRE_MASK |
+                       PMX_MCIIOWRWE_MASK,
+               .val = PMX_MCIIORDRE_MASK |
+                       PMX_MCIIOWRWE_MASK,
        },
 };
 
@@ -1613,6 +1821,12 @@ static struct spear_muxreg i2c7_dis_sd_muxreg[] = {
                .mask = PMX_MCIRESETCF_MASK |
                        PMX_MCICS0CE_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_MCIRESETCF_MASK |
+                       PMX_MCICS0CE_MASK,
+               .val = PMX_MCIRESETCF_MASK |
+                       PMX_MCICS0CE_MASK,
        },
 };
 
@@ -1651,6 +1865,14 @@ static struct spear_muxreg can0_dis_nor_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_NFRSTPWDWN3_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_NFRSTPWDWN2_MASK,
+               .val = PMX_NFRSTPWDWN2_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_NFRSTPWDWN3_MASK,
+               .val = PMX_NFRSTPWDWN3_MASK,
        },
 };
 
@@ -1677,6 +1899,10 @@ static struct spear_muxreg can0_dis_sd_muxreg[] = {
                .reg = PAD_FUNCTION_EN_2,
                .mask = PMX_MCICFINTR_MASK | PMX_MCIIORDY_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_MCICFINTR_MASK | PMX_MCIIORDY_MASK,
+               .val = PMX_MCICFINTR_MASK | PMX_MCIIORDY_MASK,
        },
 };
 
@@ -1711,6 +1937,10 @@ static struct spear_muxreg can1_dis_sd_muxreg[] = {
                .reg = PAD_FUNCTION_EN_2,
                .mask = PMX_MCICS1_MASK | PMX_MCIDMAACK_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_MCICS1_MASK | PMX_MCIDMAACK_MASK,
+               .val = PMX_MCICS1_MASK | PMX_MCIDMAACK_MASK,
        },
 };
 
@@ -1737,6 +1967,10 @@ static struct spear_muxreg can1_dis_kbd_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_KBD_ROWCOL25_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_KBD_ROWCOL25_MASK,
+               .val = PMX_KBD_ROWCOL25_MASK,
        },
 };
 
@@ -1763,29 +1997,64 @@ static struct spear_function can1_function = {
        .ngroups = ARRAY_SIZE(can1_grps),
 };
 
-/* Pad multiplexing for pci device */
-static const unsigned pci_sata_pins[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 18,
+/* Pad multiplexing for (ras-ip) pci device */
+static const unsigned pci_pins[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 18,
        19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
        37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
        55, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 };
-#define PCI_SATA_MUXREG                                \
-       {                                       \
-               .reg = PAD_FUNCTION_EN_0,       \
-               .mask = PMX_MCI_DATA8_15_MASK,  \
-               .val = 0,                       \
-       }, {                                    \
-               .reg = PAD_FUNCTION_EN_1,       \
-               .mask = PMX_PCI_REG1_MASK,      \
-               .val = 0,                       \
-       }, {                                    \
-               .reg = PAD_FUNCTION_EN_2,       \
-               .mask = PMX_PCI_REG2_MASK,      \
-               .val = 0,                       \
-       }
 
-/* pad multiplexing for pcie0 device */
+static struct spear_muxreg pci_muxreg[] = {
+       {
+               .reg = PAD_FUNCTION_EN_0,
+               .mask = PMX_MCI_DATA8_15_MASK,
+               .val = 0,
+       }, {
+               .reg = PAD_FUNCTION_EN_1,
+               .mask = PMX_PCI_REG1_MASK,
+               .val = 0,
+       }, {
+               .reg = PAD_FUNCTION_EN_2,
+               .mask = PMX_PCI_REG2_MASK,
+               .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_MCI_DATA8_15_MASK,
+               .val = PMX_MCI_DATA8_15_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_PCI_REG1_MASK,
+               .val = PMX_PCI_REG1_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_PCI_REG2_MASK,
+               .val = PMX_PCI_REG2_MASK,
+       },
+};
+
+static struct spear_modemux pci_modemux[] = {
+       {
+               .muxregs = pci_muxreg,
+               .nmuxregs = ARRAY_SIZE(pci_muxreg),
+       },
+};
+
+static struct spear_pingroup pci_pingroup = {
+       .name = "pci_grp",
+       .pins = pci_pins,
+       .npins = ARRAY_SIZE(pci_pins),
+       .modemuxs = pci_modemux,
+       .nmodemuxs = ARRAY_SIZE(pci_modemux),
+};
+
+static const char *const pci_grps[] = { "pci_grp" };
+static struct spear_function pci_function = {
+       .name = "pci",
+       .groups = pci_grps,
+       .ngroups = ARRAY_SIZE(pci_grps),
+};
+
+/* pad multiplexing for (fix-part) pcie0 device */
 static struct spear_muxreg pcie0_muxreg[] = {
-       PCI_SATA_MUXREG,
        {
                .reg = PCIE_SATA_CFG,
                .mask = PCIE_CFG_VAL(0),
@@ -1802,15 +2071,12 @@ static struct spear_modemux pcie0_modemux[] = {
 
 static struct spear_pingroup pcie0_pingroup = {
        .name = "pcie0_grp",
-       .pins = pci_sata_pins,
-       .npins = ARRAY_SIZE(pci_sata_pins),
        .modemuxs = pcie0_modemux,
        .nmodemuxs = ARRAY_SIZE(pcie0_modemux),
 };
 
-/* pad multiplexing for pcie1 device */
+/* pad multiplexing for (fix-part) pcie1 device */
 static struct spear_muxreg pcie1_muxreg[] = {
-       PCI_SATA_MUXREG,
        {
                .reg = PCIE_SATA_CFG,
                .mask = PCIE_CFG_VAL(1),
@@ -1827,15 +2093,12 @@ static struct spear_modemux pcie1_modemux[] = {
 
 static struct spear_pingroup pcie1_pingroup = {
        .name = "pcie1_grp",
-       .pins = pci_sata_pins,
-       .npins = ARRAY_SIZE(pci_sata_pins),
        .modemuxs = pcie1_modemux,
        .nmodemuxs = ARRAY_SIZE(pcie1_modemux),
 };
 
-/* pad multiplexing for pcie2 device */
+/* pad multiplexing for (fix-part) pcie2 device */
 static struct spear_muxreg pcie2_muxreg[] = {
-       PCI_SATA_MUXREG,
        {
                .reg = PCIE_SATA_CFG,
                .mask = PCIE_CFG_VAL(2),
@@ -1852,22 +2115,20 @@ static struct spear_modemux pcie2_modemux[] = {
 
 static struct spear_pingroup pcie2_pingroup = {
        .name = "pcie2_grp",
-       .pins = pci_sata_pins,
-       .npins = ARRAY_SIZE(pci_sata_pins),
        .modemuxs = pcie2_modemux,
        .nmodemuxs = ARRAY_SIZE(pcie2_modemux),
 };
 
-static const char *const pci_grps[] = { "pcie0_grp", "pcie1_grp", "pcie2_grp" };
-static struct spear_function pci_function = {
-       .name = "pci",
-       .groups = pci_grps,
-       .ngroups = ARRAY_SIZE(pci_grps),
+static const char *const pcie_grps[] = { "pcie0_grp", "pcie1_grp", "pcie2_grp"
+};
+static struct spear_function pcie_function = {
+       .name = "pci_express",
+       .groups = pcie_grps,
+       .ngroups = ARRAY_SIZE(pcie_grps),
 };
 
 /* pad multiplexing for sata0 device */
 static struct spear_muxreg sata0_muxreg[] = {
-       PCI_SATA_MUXREG,
        {
                .reg = PCIE_SATA_CFG,
                .mask = SATA_CFG_VAL(0),
@@ -1884,15 +2145,12 @@ static struct spear_modemux sata0_modemux[] = {
 
 static struct spear_pingroup sata0_pingroup = {
        .name = "sata0_grp",
-       .pins = pci_sata_pins,
-       .npins = ARRAY_SIZE(pci_sata_pins),
        .modemuxs = sata0_modemux,
        .nmodemuxs = ARRAY_SIZE(sata0_modemux),
 };
 
 /* pad multiplexing for sata1 device */
 static struct spear_muxreg sata1_muxreg[] = {
-       PCI_SATA_MUXREG,
        {
                .reg = PCIE_SATA_CFG,
                .mask = SATA_CFG_VAL(1),
@@ -1909,15 +2167,12 @@ static struct spear_modemux sata1_modemux[] = {
 
 static struct spear_pingroup sata1_pingroup = {
        .name = "sata1_grp",
-       .pins = pci_sata_pins,
-       .npins = ARRAY_SIZE(pci_sata_pins),
        .modemuxs = sata1_modemux,
        .nmodemuxs = ARRAY_SIZE(sata1_modemux),
 };
 
 /* pad multiplexing for sata2 device */
 static struct spear_muxreg sata2_muxreg[] = {
-       PCI_SATA_MUXREG,
        {
                .reg = PCIE_SATA_CFG,
                .mask = SATA_CFG_VAL(2),
@@ -1934,8 +2189,6 @@ static struct spear_modemux sata2_modemux[] = {
 
 static struct spear_pingroup sata2_pingroup = {
        .name = "sata2_grp",
-       .pins = pci_sata_pins,
-       .npins = ARRAY_SIZE(pci_sata_pins),
        .modemuxs = sata2_modemux,
        .nmodemuxs = ARRAY_SIZE(sata2_modemux),
 };
@@ -1957,6 +2210,14 @@ static struct spear_muxreg ssp1_dis_kbd_muxreg[] = {
                        PMX_KBD_COL0_MASK | PMX_NFIO8_15_MASK | PMX_NFCE1_MASK |
                        PMX_NFCE2_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_KBD_ROWCOL25_MASK | PMX_KBD_COL1_MASK |
+                       PMX_KBD_COL0_MASK | PMX_NFIO8_15_MASK | PMX_NFCE1_MASK |
+                       PMX_NFCE2_MASK,
+               .val = PMX_KBD_ROWCOL25_MASK | PMX_KBD_COL1_MASK |
+                       PMX_KBD_COL0_MASK | PMX_NFIO8_15_MASK | PMX_NFCE1_MASK |
+                       PMX_NFCE2_MASK,
        },
 };
 
@@ -1983,6 +2244,12 @@ static struct spear_muxreg ssp1_dis_sd_muxreg[] = {
                .mask = PMX_MCIADDR0ALE_MASK | PMX_MCIADDR2_MASK |
                        PMX_MCICECF_MASK | PMX_MCICEXD_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_MCIADDR0ALE_MASK | PMX_MCIADDR2_MASK |
+                       PMX_MCICECF_MASK | PMX_MCICEXD_MASK,
+               .val = PMX_MCIADDR0ALE_MASK | PMX_MCIADDR2_MASK |
+                       PMX_MCICECF_MASK | PMX_MCICEXD_MASK,
        },
 };
 
@@ -2017,6 +2284,12 @@ static struct spear_muxreg gpt64_muxreg[] = {
                .mask = PMX_MCICDCF1_MASK | PMX_MCICDCF2_MASK | PMX_MCICDXD_MASK
                        | PMX_MCILEDS_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_MCICDCF1_MASK | PMX_MCICDCF2_MASK | PMX_MCICDXD_MASK
+                       | PMX_MCILEDS_MASK,
+               .val = PMX_MCICDCF1_MASK | PMX_MCICDCF2_MASK | PMX_MCICDXD_MASK
+                       | PMX_MCILEDS_MASK,
        },
 };
 
@@ -2093,6 +2366,7 @@ static struct spear_pingroup *spear1310_pingroups[] = {
        &can0_dis_sd_pingroup,
        &can1_dis_sd_pingroup,
        &can1_dis_kbd_pingroup,
+       &pci_pingroup,
        &pcie0_pingroup,
        &pcie1_pingroup,
        &pcie2_pingroup,
@@ -2138,11 +2412,274 @@ static struct spear_function *spear1310_functions[] = {
        &can0_function,
        &can1_function,
        &pci_function,
+       &pcie_function,
        &sata_function,
        &ssp1_function,
        &gpt64_function,
 };
 
+static const unsigned pin18[] = { 18, };
+static const unsigned pin19[] = { 19, };
+static const unsigned pin20[] = { 20, };
+static const unsigned pin21[] = { 21, };
+static const unsigned pin22[] = { 22, };
+static const unsigned pin23[] = { 23, };
+static const unsigned pin54[] = { 54, };
+static const unsigned pin55[] = { 55, };
+static const unsigned pin56[] = { 56, };
+static const unsigned pin57[] = { 57, };
+static const unsigned pin58[] = { 58, };
+static const unsigned pin59[] = { 59, };
+static const unsigned pin60[] = { 60, };
+static const unsigned pin61[] = { 61, };
+static const unsigned pin62[] = { 62, };
+static const unsigned pin63[] = { 63, };
+static const unsigned pin143[] = { 143, };
+static const unsigned pin144[] = { 144, };
+static const unsigned pin145[] = { 145, };
+static const unsigned pin146[] = { 146, };
+static const unsigned pin147[] = { 147, };
+static const unsigned pin148[] = { 148, };
+static const unsigned pin149[] = { 149, };
+static const unsigned pin150[] = { 150, };
+static const unsigned pin151[] = { 151, };
+static const unsigned pin152[] = { 152, };
+static const unsigned pin205[] = { 205, };
+static const unsigned pin206[] = { 206, };
+static const unsigned pin211[] = { 211, };
+static const unsigned pin212[] = { 212, };
+static const unsigned pin213[] = { 213, };
+static const unsigned pin214[] = { 214, };
+static const unsigned pin215[] = { 215, };
+static const unsigned pin216[] = { 216, };
+static const unsigned pin217[] = { 217, };
+static const unsigned pin218[] = { 218, };
+static const unsigned pin219[] = { 219, };
+static const unsigned pin220[] = { 220, };
+static const unsigned pin221[] = { 221, };
+static const unsigned pin222[] = { 222, };
+static const unsigned pin223[] = { 223, };
+static const unsigned pin224[] = { 224, };
+static const unsigned pin225[] = { 225, };
+static const unsigned pin226[] = { 226, };
+static const unsigned pin227[] = { 227, };
+static const unsigned pin228[] = { 228, };
+static const unsigned pin229[] = { 229, };
+static const unsigned pin230[] = { 230, };
+static const unsigned pin231[] = { 231, };
+static const unsigned pin232[] = { 232, };
+static const unsigned pin233[] = { 233, };
+static const unsigned pin234[] = { 234, };
+static const unsigned pin235[] = { 235, };
+static const unsigned pin236[] = { 236, };
+static const unsigned pin237[] = { 237, };
+static const unsigned pin238[] = { 238, };
+static const unsigned pin239[] = { 239, };
+static const unsigned pin240[] = { 240, };
+static const unsigned pin241[] = { 241, };
+static const unsigned pin242[] = { 242, };
+static const unsigned pin243[] = { 243, };
+static const unsigned pin244[] = { 244, };
+static const unsigned pin245[] = { 245, };
+
+static const unsigned pin_grp0[] = { 173, 174, };
+static const unsigned pin_grp1[] = { 175, 185, 188, 197, 198, };
+static const unsigned pin_grp2[] = { 176, 177, 178, 179, 184, 186, 187, 189,
+       190, 191, 192, };
+static const unsigned pin_grp3[] = { 180, 181, 182, 183, 193, 194, 195, 196, };
+static const unsigned pin_grp4[] = { 199, 200, };
+static const unsigned pin_grp5[] = { 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+       75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, };
+static const unsigned pin_grp6[] = { 86, 87, 88, 89, 90, 91, 92, 93, };
+static const unsigned pin_grp7[] = { 98, 99, };
+static const unsigned pin_grp8[] = { 158, 159, 160, 161, 162, 163, 164, 165,
+       166, 167, 168, 169, 170, 171, 172, };
+
+/* Define muxreg arrays */
+DEFINE_2_MUXREG(i2c0_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_I2C0_MASK, 0, 1);
+DEFINE_2_MUXREG(ssp0_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_SSP0_MASK, 0, 1);
+DEFINE_2_MUXREG(ssp0_cs0_pins, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_SSP0_CS0_MASK, 0, 1);
+DEFINE_2_MUXREG(ssp0_cs1_2_pins, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_SSP0_CS1_2_MASK, 0, 1);
+DEFINE_2_MUXREG(i2s0_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_I2S0_MASK, 0, 1);
+DEFINE_2_MUXREG(i2s1_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_I2S1_MASK, 0, 1);
+DEFINE_2_MUXREG(clcd_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_CLCD1_MASK, 0, 1);
+DEFINE_2_MUXREG(clcd_high_res_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_CLCD2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin18, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO15_MASK, 0, 1);
+DEFINE_2_MUXREG(pin19, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO14_MASK, 0, 1);
+DEFINE_2_MUXREG(pin20, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO13_MASK, 0, 1);
+DEFINE_2_MUXREG(pin21, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO12_MASK, 0, 1);
+DEFINE_2_MUXREG(pin22, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO11_MASK, 0, 1);
+DEFINE_2_MUXREG(pin23, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO10_MASK, 0, 1);
+DEFINE_2_MUXREG(pin143, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO00_MASK, 0, 1);
+DEFINE_2_MUXREG(pin144, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO01_MASK, 0, 1);
+DEFINE_2_MUXREG(pin145, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO02_MASK, 0, 1);
+DEFINE_2_MUXREG(pin146, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO03_MASK, 0, 1);
+DEFINE_2_MUXREG(pin147, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO04_MASK, 0, 1);
+DEFINE_2_MUXREG(pin148, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO05_MASK, 0, 1);
+DEFINE_2_MUXREG(pin149, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO06_MASK, 0, 1);
+DEFINE_2_MUXREG(pin150, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO07_MASK, 0, 1);
+DEFINE_2_MUXREG(pin151, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO08_MASK, 0, 1);
+DEFINE_2_MUXREG(pin152, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO09_MASK, 0, 1);
+DEFINE_2_MUXREG(smi_2_chips_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_SMI_MASK, 0, 1);
+DEFINE_2_MUXREG(pin54, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_SMINCS3_MASK, 0, 1);
+DEFINE_2_MUXREG(pin55, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_SMINCS2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin56, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_NFRSTPWDWN3_MASK, 0, 1);
+DEFINE_2_MUXREG(pin57, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFRSTPWDWN2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin58, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFRSTPWDWN1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin59, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFRSTPWDWN0_MASK, 0, 1);
+DEFINE_2_MUXREG(pin60, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFWPRT3_MASK, 0, 1);
+DEFINE_2_MUXREG(pin61, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFCE3_MASK, 0, 1);
+DEFINE_2_MUXREG(pin62, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFAD25_MASK, 0, 1);
+DEFINE_2_MUXREG(pin63, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFAD24_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp0, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_GMIICLK_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp1, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_GMIICOL_CRS_XFERER_MIITXCLK_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp2, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_RXCLK_RDV_TXEN_D03_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp3, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_GMIID47_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp4, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_MDC_MDIO_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp5, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFAD23_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp6, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_MCI_DATA8_15_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp7, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_NFCE2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp8, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_NAND8_MASK, 0, 1);
+DEFINE_2_MUXREG(nand_16bit_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_NAND16BIT_1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin205, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_COL1_MASK | PMX_NFCE1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin206, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_COL0_MASK | PMX_NFCE2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin211, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_ROW1_MASK | PMX_NFWPRT1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin212, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_ROW0_MASK | PMX_NFWPRT2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin213, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA0_MASK, 0, 1);
+DEFINE_2_MUXREG(pin214, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin215, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin216, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA3_MASK, 0, 1);
+DEFINE_2_MUXREG(pin217, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA4_MASK, 0, 1);
+DEFINE_2_MUXREG(pin218, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA5_MASK, 0, 1);
+DEFINE_2_MUXREG(pin219, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA6_MASK, 0, 1);
+DEFINE_2_MUXREG(pin220, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA7_MASK, 0, 1);
+DEFINE_2_MUXREG(pin221, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA1SD_MASK, 0, 1);
+DEFINE_2_MUXREG(pin222, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA2SD_MASK, 0, 1);
+DEFINE_2_MUXREG(pin223, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA3SD_MASK, 0, 1);
+DEFINE_2_MUXREG(pin224, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIADDR0ALE_MASK, 0, 1);
+DEFINE_2_MUXREG(pin225, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIADDR1CLECLK_MASK, 0, 1);
+DEFINE_2_MUXREG(pin226, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIADDR2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin227, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICECF_MASK, 0, 1);
+DEFINE_2_MUXREG(pin228, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICEXD_MASK, 0, 1);
+DEFINE_2_MUXREG(pin229, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICESDMMC_MASK, 0, 1);
+DEFINE_2_MUXREG(pin230, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICDCF1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin231, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICDCF2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin232, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICDXD_MASK, 0, 1);
+DEFINE_2_MUXREG(pin233, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICDSDMMC_MASK, 0, 1);
+DEFINE_2_MUXREG(pin234, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATADIR_MASK, 0, 1);
+DEFINE_2_MUXREG(pin235, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDMARQWP_MASK, 0, 1);
+DEFINE_2_MUXREG(pin236, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIIORDRE_MASK, 0, 1);
+DEFINE_2_MUXREG(pin237, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIIOWRWE_MASK, 0, 1);
+DEFINE_2_MUXREG(pin238, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIRESETCF_MASK, 0, 1);
+DEFINE_2_MUXREG(pin239, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICS0CE_MASK, 0, 1);
+DEFINE_2_MUXREG(pin240, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICFINTR_MASK, 0, 1);
+DEFINE_2_MUXREG(pin241, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIIORDY_MASK, 0, 1);
+DEFINE_2_MUXREG(pin242, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICS1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin243, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDMAACK_MASK, 0, 1);
+DEFINE_2_MUXREG(pin244, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCISDCMD_MASK, 0, 1);
+DEFINE_2_MUXREG(pin245, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCILEDS_MASK, 0, 1);
+DEFINE_2_MUXREG(keyboard_rowcol6_8_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_ROWCOL68_MASK, 0, 1);
+DEFINE_2_MUXREG(uart0_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_UART0_MASK, 0, 1);
+DEFINE_2_MUXREG(uart0_modem_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_UART0_MODEM_MASK, 0, 1);
+DEFINE_2_MUXREG(gpt0_tmr0_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_GPT0_TMR0_MASK, 0, 1);
+DEFINE_2_MUXREG(gpt0_tmr1_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_GPT0_TMR1_MASK, 0, 1);
+DEFINE_2_MUXREG(gpt1_tmr0_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_GPT1_TMR0_MASK, 0, 1);
+DEFINE_2_MUXREG(gpt1_tmr1_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_GPT1_TMR1_MASK, 0, 1);
+DEFINE_2_MUXREG(touch_xy_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_TOUCH_XY_MASK, 0, 1);
+
+static struct spear_gpio_pingroup spear1310_gpio_pingroup[] = {
+       GPIO_PINGROUP(i2c0_pins),
+       GPIO_PINGROUP(ssp0_pins),
+       GPIO_PINGROUP(ssp0_cs0_pins),
+       GPIO_PINGROUP(ssp0_cs1_2_pins),
+       GPIO_PINGROUP(i2s0_pins),
+       GPIO_PINGROUP(i2s1_pins),
+       GPIO_PINGROUP(clcd_pins),
+       GPIO_PINGROUP(clcd_high_res_pins),
+       GPIO_PINGROUP(pin18),
+       GPIO_PINGROUP(pin19),
+       GPIO_PINGROUP(pin20),
+       GPIO_PINGROUP(pin21),
+       GPIO_PINGROUP(pin22),
+       GPIO_PINGROUP(pin23),
+       GPIO_PINGROUP(pin143),
+       GPIO_PINGROUP(pin144),
+       GPIO_PINGROUP(pin145),
+       GPIO_PINGROUP(pin146),
+       GPIO_PINGROUP(pin147),
+       GPIO_PINGROUP(pin148),
+       GPIO_PINGROUP(pin149),
+       GPIO_PINGROUP(pin150),
+       GPIO_PINGROUP(pin151),
+       GPIO_PINGROUP(pin152),
+       GPIO_PINGROUP(smi_2_chips_pins),
+       GPIO_PINGROUP(pin54),
+       GPIO_PINGROUP(pin55),
+       GPIO_PINGROUP(pin56),
+       GPIO_PINGROUP(pin57),
+       GPIO_PINGROUP(pin58),
+       GPIO_PINGROUP(pin59),
+       GPIO_PINGROUP(pin60),
+       GPIO_PINGROUP(pin61),
+       GPIO_PINGROUP(pin62),
+       GPIO_PINGROUP(pin63),
+       GPIO_PINGROUP(pin_grp0),
+       GPIO_PINGROUP(pin_grp1),
+       GPIO_PINGROUP(pin_grp2),
+       GPIO_PINGROUP(pin_grp3),
+       GPIO_PINGROUP(pin_grp4),
+       GPIO_PINGROUP(pin_grp5),
+       GPIO_PINGROUP(pin_grp6),
+       GPIO_PINGROUP(pin_grp7),
+       GPIO_PINGROUP(pin_grp8),
+       GPIO_PINGROUP(nand_16bit_pins),
+       GPIO_PINGROUP(pin205),
+       GPIO_PINGROUP(pin206),
+       GPIO_PINGROUP(pin211),
+       GPIO_PINGROUP(pin212),
+       GPIO_PINGROUP(pin213),
+       GPIO_PINGROUP(pin214),
+       GPIO_PINGROUP(pin215),
+       GPIO_PINGROUP(pin216),
+       GPIO_PINGROUP(pin217),
+       GPIO_PINGROUP(pin218),
+       GPIO_PINGROUP(pin219),
+       GPIO_PINGROUP(pin220),
+       GPIO_PINGROUP(pin221),
+       GPIO_PINGROUP(pin222),
+       GPIO_PINGROUP(pin223),
+       GPIO_PINGROUP(pin224),
+       GPIO_PINGROUP(pin225),
+       GPIO_PINGROUP(pin226),
+       GPIO_PINGROUP(pin227),
+       GPIO_PINGROUP(pin228),
+       GPIO_PINGROUP(pin229),
+       GPIO_PINGROUP(pin230),
+       GPIO_PINGROUP(pin231),
+       GPIO_PINGROUP(pin232),
+       GPIO_PINGROUP(pin233),
+       GPIO_PINGROUP(pin234),
+       GPIO_PINGROUP(pin235),
+       GPIO_PINGROUP(pin236),
+       GPIO_PINGROUP(pin237),
+       GPIO_PINGROUP(pin238),
+       GPIO_PINGROUP(pin239),
+       GPIO_PINGROUP(pin240),
+       GPIO_PINGROUP(pin241),
+       GPIO_PINGROUP(pin242),
+       GPIO_PINGROUP(pin243),
+       GPIO_PINGROUP(pin244),
+       GPIO_PINGROUP(pin245),
+       GPIO_PINGROUP(keyboard_rowcol6_8_pins),
+       GPIO_PINGROUP(uart0_pins),
+       GPIO_PINGROUP(uart0_modem_pins),
+       GPIO_PINGROUP(gpt0_tmr0_pins),
+       GPIO_PINGROUP(gpt0_tmr1_pins),
+       GPIO_PINGROUP(gpt1_tmr0_pins),
+       GPIO_PINGROUP(gpt1_tmr1_pins),
+       GPIO_PINGROUP(touch_xy_pins),
+};
+
 static struct spear_pinctrl_machdata spear1310_machdata = {
        .pins = spear1310_pins,
        .npins = ARRAY_SIZE(spear1310_pins),
@@ -2150,6 +2687,8 @@ static struct spear_pinctrl_machdata spear1310_machdata = {
        .ngroups = ARRAY_SIZE(spear1310_pingroups),
        .functions = spear1310_functions,
        .nfunctions = ARRAY_SIZE(spear1310_functions),
+       .gpio_pingroups = spear1310_gpio_pingroup,
+       .ngpio_pingroups = ARRAY_SIZE(spear1310_gpio_pingroup),
        .modes_supported = false,
 };
 
index a0eb057..0b4af0e 100644 (file)
@@ -213,7 +213,7 @@ static const struct pinctrl_pin_desc spear1340_pins[] = {
  * Pad multiplexing for making all pads as gpio's. This is done to override the
  * values passed from bootloader and start from scratch.
  */
-static const unsigned pads_as_gpio_pins[] = { 251 };
+static const unsigned pads_as_gpio_pins[] = { 12, 88, 89, 251 };
 static struct spear_muxreg pads_as_gpio_muxreg[] = {
        {
                .reg = PAD_FUNCTION_EN_1,
@@ -1692,7 +1692,43 @@ static struct spear_pingroup clcd_pingroup = {
        .nmodemuxs = ARRAY_SIZE(clcd_modemux),
 };
 
-static const char *const clcd_grps[] = { "clcd_grp" };
+/* Disable cld runtime to save panel damage */
+static struct spear_muxreg clcd_sleep_muxreg[] = {
+       {
+               .reg = PAD_SHARED_IP_EN_1,
+               .mask = ARM_TRACE_MASK | MIPHY_DBG_MASK,
+               .val = 0,
+       }, {
+               .reg = PAD_FUNCTION_EN_5,
+               .mask = CLCD_REG4_MASK | CLCD_AND_ARM_TRACE_REG4_MASK,
+               .val = 0x0,
+       }, {
+               .reg = PAD_FUNCTION_EN_6,
+               .mask = CLCD_AND_ARM_TRACE_REG5_MASK,
+               .val = 0x0,
+       }, {
+               .reg = PAD_FUNCTION_EN_7,
+               .mask = CLCD_AND_ARM_TRACE_REG6_MASK,
+               .val = 0x0,
+       },
+};
+
+static struct spear_modemux clcd_sleep_modemux[] = {
+       {
+               .muxregs = clcd_sleep_muxreg,
+               .nmuxregs = ARRAY_SIZE(clcd_sleep_muxreg),
+       },
+};
+
+static struct spear_pingroup clcd_sleep_pingroup = {
+       .name = "clcd_sleep_grp",
+       .pins = clcd_pins,
+       .npins = ARRAY_SIZE(clcd_pins),
+       .modemuxs = clcd_sleep_modemux,
+       .nmodemuxs = ARRAY_SIZE(clcd_sleep_modemux),
+};
+
+static const char *const clcd_grps[] = { "clcd_grp", "clcd_sleep_grp" };
 static struct spear_function clcd_function = {
        .name = "clcd",
        .groups = clcd_grps,
@@ -1893,6 +1929,7 @@ static struct spear_pingroup *spear1340_pingroups[] = {
        &sdhci_pingroup,
        &cf_pingroup,
        &xd_pingroup,
+       &clcd_sleep_pingroup,
        &clcd_pingroup,
        &arm_trace_pingroup,
        &miphy_dbg_pingroup,
@@ -1934,6 +1971,32 @@ static struct spear_function *spear1340_functions[] = {
        &sata_function,
 };
 
+static void gpio_request_endisable(struct spear_pmx *pmx, int pin,
+               bool enable)
+{
+       unsigned int regoffset, regindex, bitoffset;
+       unsigned int val;
+
+       /* pin++ as gpio configuration starts from 2nd bit of base register */
+       pin++;
+
+       regindex = pin / 32;
+       bitoffset = pin % 32;
+
+       if (regindex <= 3)
+               regoffset = PAD_FUNCTION_EN_1 + regindex * sizeof(int *);
+       else
+               regoffset = PAD_FUNCTION_EN_5 + (regindex - 4) * sizeof(int *);
+
+       val = pmx_readl(pmx, regoffset);
+       if (enable)
+               val &= ~(0x1 << bitoffset);
+       else
+               val |= 0x1 << bitoffset;
+
+       pmx_writel(pmx, val, regoffset);
+}
+
 static struct spear_pinctrl_machdata spear1340_machdata = {
        .pins = spear1340_pins,
        .npins = ARRAY_SIZE(spear1340_pins),
@@ -1941,6 +2004,7 @@ static struct spear_pinctrl_machdata spear1340_machdata = {
        .ngroups = ARRAY_SIZE(spear1340_pingroups),
        .functions = spear1340_functions,
        .nfunctions = ARRAY_SIZE(spear1340_functions),
+       .gpio_request_endisable = gpio_request_endisable,
        .modes_supported = false,
 };
 
index 4dfc284..9a49100 100644 (file)
@@ -661,6 +661,8 @@ static int __devinit spear300_pinctrl_probe(struct platform_device *pdev)
        spear3xx_machdata.ngroups = ARRAY_SIZE(spear300_pingroups);
        spear3xx_machdata.functions = spear300_functions;
        spear3xx_machdata.nfunctions = ARRAY_SIZE(spear300_functions);
+       spear3xx_machdata.gpio_pingroups = NULL;
+       spear3xx_machdata.ngpio_pingroups = 0;
 
        spear3xx_machdata.modes_supported = true;
        spear3xx_machdata.pmx_modes = spear300_pmx_modes;
index 9688369..4d5dfe9 100644 (file)
@@ -388,6 +388,8 @@ static int __devinit spear310_pinctrl_probe(struct platform_device *pdev)
        spear3xx_machdata.nfunctions = ARRAY_SIZE(spear310_functions);
 
        pmx_init_addr(&spear3xx_machdata, PMX_CONFIG_REG);
+       pmx_init_gpio_pingroup_addr(spear3xx_machdata.gpio_pingroups,
+                       spear3xx_machdata.ngpio_pingroups, PMX_CONFIG_REG);
 
        spear3xx_machdata.modes_supported = false;
 
index 020b1e0..c996e26 100644 (file)
@@ -2240,6 +2240,10 @@ static struct spear_muxreg pwm2_pin_34_muxreg[] = {
                .mask = PMX_SSP_CS_MASK,
                .val = 0,
        }, {
+               .reg = MODE_CONFIG_REG,
+               .mask = PMX_PWM_MASK,
+               .val = PMX_PWM_MASK,
+       }, {
                .reg = IP_SEL_PAD_30_39_REG,
                .mask = PMX_PL_34_MASK,
                .val = PMX_PWM2_PL_34_VAL,
@@ -2956,9 +2960,9 @@ static struct spear_function mii2_function = {
 };
 
 /* Pad multiplexing for cadence mii 1_2 as smii or rmii device */
-static const unsigned smii0_1_pins[] = { 10, 11, 13, 14, 15, 16, 17, 18, 19, 20,
+static const unsigned rmii0_1_pins[] = { 10, 11, 13, 14, 15, 16, 17, 18, 19, 20,
        21, 22, 23, 24, 25, 26, 27 };
-static const unsigned rmii0_1_pins[] = { 10, 11, 21, 22, 23, 24, 25, 26, 27 };
+static const unsigned smii0_1_pins[] = { 10, 11, 21, 22, 23, 24, 25, 26, 27 };
 static struct spear_muxreg mii0_1_muxreg[] = {
        {
                .reg = PMX_CONFIG_REG,
@@ -3427,6 +3431,8 @@ static int __devinit spear320_pinctrl_probe(struct platform_device *pdev)
        spear3xx_machdata.npmx_modes = ARRAY_SIZE(spear320_pmx_modes);
 
        pmx_init_addr(&spear3xx_machdata, PMX_CONFIG_REG);
+       pmx_init_gpio_pingroup_addr(spear3xx_machdata.gpio_pingroups,
+                       spear3xx_machdata.ngpio_pingroups, PMX_CONFIG_REG);
 
        ret = spear_pinctrl_probe(pdev, &spear3xx_machdata);
        if (ret)
index 0242378..12ee21a 100644 (file)
@@ -481,7 +481,44 @@ struct spear_function spear3xx_timer_2_3_function = {
        .ngroups = ARRAY_SIZE(timer_2_3_grps),
 };
 
+/* Define muxreg arrays */
+DEFINE_MUXREG(firda_pins, 0, PMX_FIRDA_MASK, 0);
+DEFINE_MUXREG(i2c_pins, 0, PMX_I2C_MASK, 0);
+DEFINE_MUXREG(ssp_cs_pins, 0, PMX_SSP_CS_MASK, 0);
+DEFINE_MUXREG(ssp_pins, 0, PMX_SSP_MASK, 0);
+DEFINE_MUXREG(mii_pins, 0, PMX_MII_MASK, 0);
+DEFINE_MUXREG(gpio0_pin0_pins, 0, PMX_GPIO_PIN0_MASK, 0);
+DEFINE_MUXREG(gpio0_pin1_pins, 0, PMX_GPIO_PIN1_MASK, 0);
+DEFINE_MUXREG(gpio0_pin2_pins, 0, PMX_GPIO_PIN2_MASK, 0);
+DEFINE_MUXREG(gpio0_pin3_pins, 0, PMX_GPIO_PIN3_MASK, 0);
+DEFINE_MUXREG(gpio0_pin4_pins, 0, PMX_GPIO_PIN4_MASK, 0);
+DEFINE_MUXREG(gpio0_pin5_pins, 0, PMX_GPIO_PIN5_MASK, 0);
+DEFINE_MUXREG(uart0_ext_pins, 0, PMX_UART0_MODEM_MASK, 0);
+DEFINE_MUXREG(uart0_pins, 0, PMX_UART0_MASK, 0);
+DEFINE_MUXREG(timer_0_1_pins, 0, PMX_TIMER_0_1_MASK, 0);
+DEFINE_MUXREG(timer_2_3_pins, 0, PMX_TIMER_2_3_MASK, 0);
+
+static struct spear_gpio_pingroup spear3xx_gpio_pingroup[] = {
+       GPIO_PINGROUP(firda_pins),
+       GPIO_PINGROUP(i2c_pins),
+       GPIO_PINGROUP(ssp_cs_pins),
+       GPIO_PINGROUP(ssp_pins),
+       GPIO_PINGROUP(mii_pins),
+       GPIO_PINGROUP(gpio0_pin0_pins),
+       GPIO_PINGROUP(gpio0_pin1_pins),
+       GPIO_PINGROUP(gpio0_pin2_pins),
+       GPIO_PINGROUP(gpio0_pin3_pins),
+       GPIO_PINGROUP(gpio0_pin4_pins),
+       GPIO_PINGROUP(gpio0_pin5_pins),
+       GPIO_PINGROUP(uart0_ext_pins),
+       GPIO_PINGROUP(uart0_pins),
+       GPIO_PINGROUP(timer_0_1_pins),
+       GPIO_PINGROUP(timer_2_3_pins),
+};
+
 struct spear_pinctrl_machdata spear3xx_machdata = {
        .pins = spear3xx_pins,
        .npins = ARRAY_SIZE(spear3xx_pins),
+       .gpio_pingroups = spear3xx_gpio_pingroup,
+       .ngpio_pingroups = ARRAY_SIZE(spear3xx_gpio_pingroup),
 };
index 31f4434..7860b36 100644 (file)
@@ -15,6 +15,7 @@
 #include "pinctrl-spear.h"
 
 /* pad mux declarations */
+#define PMX_PWM_MASK           (1 << 16)
 #define PMX_FIRDA_MASK         (1 << 14)
 #define PMX_I2C_MASK           (1 << 13)
 #define PMX_SSP_CS_MASK                (1 << 12)
index fa4e0a5..ffd53e3 100644 (file)
@@ -159,6 +159,8 @@ struct pnp_resource {
 
 void pnp_free_resource(struct pnp_resource *pnp_res);
 
+struct pnp_resource *pnp_add_resource(struct pnp_dev *dev,
+                                     struct resource *res);
 struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
                                          int flags);
 struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
index 26b5d4b..72e822e 100644 (file)
@@ -58,7 +58,7 @@ static inline int __init is_exclusive_device(struct acpi_device *dev)
        if (!(('0' <= (c) && (c) <= '9') || ('A' <= (c) && (c) <= 'F'))) \
                return 0
 #define TEST_ALPHA(c) \
-       if (!('@' <= (c) || (c) <= 'Z')) \
+       if (!('A' <= (c) && (c) <= 'Z')) \
                return 0
 static int __init ispnpidacpi(const char *id)
 {
@@ -95,6 +95,9 @@ static int pnpacpi_set_resources(struct pnp_dev *dev)
                return -ENODEV;
        }
 
+       if (WARN_ON_ONCE(acpi_dev != dev->data))
+               dev->data = acpi_dev;
+
        ret = pnpacpi_build_resource_template(dev, &buffer);
        if (ret)
                return ret;
@@ -242,6 +245,10 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
        char *pnpid;
        struct acpi_hardware_id *id;
 
+       /* Skip devices that are already bound */
+       if (device->physical_node_count)
+               return 0;
+
        /*
         * If a PnPacpi device is not present , the device
         * driver should not be loaded.
index 5be4a39..b8f4ea7 100644 (file)
 #include "../base.h"
 #include "pnpacpi.h"
 
-#ifdef CONFIG_IA64
-#define valid_IRQ(i) (1)
-#else
-#define valid_IRQ(i) (((i) != 0) && ((i) != 2))
-#endif
-
-/*
- * Allocated Resources
- */
-static int irq_flags(int triggering, int polarity, int shareable)
-{
-       int flags;
-
-       if (triggering == ACPI_LEVEL_SENSITIVE) {
-               if (polarity == ACPI_ACTIVE_LOW)
-                       flags = IORESOURCE_IRQ_LOWLEVEL;
-               else
-                       flags = IORESOURCE_IRQ_HIGHLEVEL;
-       } else {
-               if (polarity == ACPI_ACTIVE_LOW)
-                       flags = IORESOURCE_IRQ_LOWEDGE;
-               else
-                       flags = IORESOURCE_IRQ_HIGHEDGE;
-       }
-
-       if (shareable == ACPI_SHARED)
-               flags |= IORESOURCE_IRQ_SHAREABLE;
-
-       return flags;
-}
-
 static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering,
                             int *polarity, int *shareable)
 {
@@ -94,45 +63,6 @@ static void decode_irq_flags(struct pnp_dev *dev, int flags, int *triggering,
                *shareable = ACPI_EXCLUSIVE;
 }
 
-static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev,
-                                               u32 gsi, int triggering,
-                                               int polarity, int shareable)
-{
-       int irq, flags;
-       int p, t;
-
-       if (!valid_IRQ(gsi)) {
-               pnp_add_irq_resource(dev, gsi, IORESOURCE_DISABLED);
-               return;
-       }
-
-       /*
-        * in IO-APIC mode, use overrided attribute. Two reasons:
-        * 1. BIOS bug in DSDT
-        * 2. BIOS uses IO-APIC mode Interrupt Source Override
-        */
-       if (!acpi_get_override_irq(gsi, &t, &p)) {
-               t = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
-               p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
-
-               if (triggering != t || polarity != p) {
-                       dev_warn(&dev->dev, "IRQ %d override to %s, %s\n",
-                               gsi, t ? "edge":"level", p ? "low":"high");
-                       triggering = t;
-                       polarity = p;
-               }
-       }
-
-       flags = irq_flags(triggering, polarity, shareable);
-       irq = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
-       if (irq >= 0)
-               pcibios_penalize_isa_irq(irq, 1);
-       else
-               flags |= IORESOURCE_DISABLED;
-
-       pnp_add_irq_resource(dev, irq, flags);
-}
-
 static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
                     int transfer)
 {
@@ -177,21 +107,16 @@ static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
        return flags;
 }
 
-static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start,
-                                              u64 len, int io_decode,
-                                              int window)
-{
-       int flags = 0;
-       u64 end = start + len - 1;
+/*
+ * Allocated Resources
+ */
 
-       if (io_decode == ACPI_DECODE_16)
-               flags |= IORESOURCE_IO_16BIT_ADDR;
-       if (len == 0 || end >= 0x10003)
-               flags |= IORESOURCE_DISABLED;
-       if (window)
-               flags |= IORESOURCE_WINDOW;
+static void pnpacpi_add_irqresource(struct pnp_dev *dev, struct resource *r)
+{
+       if (!(r->flags & IORESOURCE_DISABLED))
+               pcibios_penalize_isa_irq(r->start, 1);
 
-       pnp_add_io_resource(dev, start, end, flags);
+       pnp_add_resource(dev, r);
 }
 
 /*
@@ -249,130 +174,49 @@ static void pnpacpi_parse_allocated_vendor(struct pnp_dev *dev,
        }
 }
 
-static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
-                                               u64 start, u64 len,
-                                               int write_protect, int window)
-{
-       int flags = 0;
-       u64 end = start + len - 1;
-
-       if (len == 0)
-               flags |= IORESOURCE_DISABLED;
-       if (write_protect == ACPI_READ_WRITE_MEMORY)
-               flags |= IORESOURCE_MEM_WRITEABLE;
-       if (window)
-               flags |= IORESOURCE_WINDOW;
-
-       pnp_add_mem_resource(dev, start, end, flags);
-}
-
-static void pnpacpi_parse_allocated_busresource(struct pnp_dev *dev,
-                                               u64 start, u64 len)
-{
-       u64 end = start + len - 1;
-
-       pnp_add_bus_resource(dev, start, end);
-}
-
-static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
-                                                 struct acpi_resource *res)
-{
-       struct acpi_resource_address64 addr, *p = &addr;
-       acpi_status status;
-       int window;
-       u64 len;
-
-       status = acpi_resource_to_address64(res, p);
-       if (!ACPI_SUCCESS(status)) {
-               dev_warn(&dev->dev, "failed to convert resource type %d\n",
-                        res->type);
-               return;
-       }
-
-       /* Windows apparently computes length rather than using _LEN */
-       len = p->maximum - p->minimum + 1;
-       window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
-
-       if (p->resource_type == ACPI_MEMORY_RANGE)
-               pnpacpi_parse_allocated_memresource(dev, p->minimum, len,
-                       p->info.mem.write_protect, window);
-       else if (p->resource_type == ACPI_IO_RANGE)
-               pnpacpi_parse_allocated_ioresource(dev, p->minimum, len,
-                       p->granularity == 0xfff ? ACPI_DECODE_10 :
-                               ACPI_DECODE_16, window);
-       else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
-               pnpacpi_parse_allocated_busresource(dev, p->minimum, len);
-}
-
-static void pnpacpi_parse_allocated_ext_address_space(struct pnp_dev *dev,
-                                                     struct acpi_resource *res)
-{
-       struct acpi_resource_extended_address64 *p = &res->data.ext_address64;
-       int window;
-       u64 len;
-
-       /* Windows apparently computes length rather than using _LEN */
-       len = p->maximum - p->minimum + 1;
-       window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
-
-       if (p->resource_type == ACPI_MEMORY_RANGE)
-               pnpacpi_parse_allocated_memresource(dev, p->minimum, len,
-                       p->info.mem.write_protect, window);
-       else if (p->resource_type == ACPI_IO_RANGE)
-               pnpacpi_parse_allocated_ioresource(dev, p->minimum, len,
-                       p->granularity == 0xfff ? ACPI_DECODE_10 :
-                               ACPI_DECODE_16, window);
-       else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
-               pnpacpi_parse_allocated_busresource(dev, p->minimum, len);
-}
-
 static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
                                              void *data)
 {
        struct pnp_dev *dev = data;
-       struct acpi_resource_irq *irq;
        struct acpi_resource_dma *dma;
-       struct acpi_resource_io *io;
-       struct acpi_resource_fixed_io *fixed_io;
        struct acpi_resource_vendor_typed *vendor_typed;
-       struct acpi_resource_memory24 *memory24;
-       struct acpi_resource_memory32 *memory32;
-       struct acpi_resource_fixed_memory32 *fixed_memory32;
-       struct acpi_resource_extended_irq *extended_irq;
+       struct resource r;
        int i, flags;
 
-       switch (res->type) {
-       case ACPI_RESOURCE_TYPE_IRQ:
-               /*
-                * Per spec, only one interrupt per descriptor is allowed in
-                * _CRS, but some firmware violates this, so parse them all.
-                */
-               irq = &res->data.irq;
-               if (irq->interrupt_count == 0)
-                       pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
-               else {
-                       for (i = 0; i < irq->interrupt_count; i++) {
-                               pnpacpi_parse_allocated_irqresource(dev,
-                                       irq->interrupts[i],
-                                       irq->triggering,
-                                       irq->polarity,
-                                   irq->sharable);
-                       }
+       if (acpi_dev_resource_memory(res, &r)
+           || acpi_dev_resource_io(res, &r)
+           || acpi_dev_resource_address_space(res, &r)
+           || acpi_dev_resource_ext_address_space(res, &r)) {
+               pnp_add_resource(dev, &r);
+               return AE_OK;
+       }
 
+       r.flags = 0;
+       if (acpi_dev_resource_interrupt(res, 0, &r)) {
+               pnpacpi_add_irqresource(dev, &r);
+               for (i = 1; acpi_dev_resource_interrupt(res, i, &r); i++)
+                       pnpacpi_add_irqresource(dev, &r);
+
+               if (i > 1) {
                        /*
                         * The IRQ encoder puts a single interrupt in each
                         * descriptor, so if a _CRS descriptor has more than
                         * one interrupt, we won't be able to re-encode it.
                         */
-                       if (pnp_can_write(dev) && irq->interrupt_count > 1) {
+                       if (pnp_can_write(dev)) {
                                dev_warn(&dev->dev, "multiple interrupts in "
                                         "_CRS descriptor; configuration can't "
                                         "be changed\n");
                                dev->capabilities &= ~PNP_WRITE;
                        }
                }
-               break;
+               return AE_OK;
+       } else if (r.flags & IORESOURCE_DISABLED) {
+               pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
+               return AE_OK;
+       }
 
+       switch (res->type) {
        case ACPI_RESOURCE_TYPE_DMA:
                dma = &res->data.dma;
                if (dma->channel_count > 0 && dma->channels[0] != (u8) -1)
@@ -383,26 +227,10 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
                pnp_add_dma_resource(dev, dma->channels[0], flags);
                break;
 
-       case ACPI_RESOURCE_TYPE_IO:
-               io = &res->data.io;
-               pnpacpi_parse_allocated_ioresource(dev,
-                       io->minimum,
-                       io->address_length,
-                       io->io_decode, 0);
-               break;
-
        case ACPI_RESOURCE_TYPE_START_DEPENDENT:
        case ACPI_RESOURCE_TYPE_END_DEPENDENT:
                break;
 
-       case ACPI_RESOURCE_TYPE_FIXED_IO:
-               fixed_io = &res->data.fixed_io;
-               pnpacpi_parse_allocated_ioresource(dev,
-                       fixed_io->address,
-                       fixed_io->address_length,
-                       ACPI_DECODE_10, 0);
-               break;
-
        case ACPI_RESOURCE_TYPE_VENDOR:
                vendor_typed = &res->data.vendor_typed;
                pnpacpi_parse_allocated_vendor(dev, vendor_typed);
@@ -411,66 +239,6 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
        case ACPI_RESOURCE_TYPE_END_TAG:
                break;
 
-       case ACPI_RESOURCE_TYPE_MEMORY24:
-               memory24 = &res->data.memory24;
-               pnpacpi_parse_allocated_memresource(dev,
-                       memory24->minimum,
-                       memory24->address_length,
-                       memory24->write_protect, 0);
-               break;
-       case ACPI_RESOURCE_TYPE_MEMORY32:
-               memory32 = &res->data.memory32;
-               pnpacpi_parse_allocated_memresource(dev,
-                       memory32->minimum,
-                       memory32->address_length,
-                       memory32->write_protect, 0);
-               break;
-       case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
-               fixed_memory32 = &res->data.fixed_memory32;
-               pnpacpi_parse_allocated_memresource(dev,
-                       fixed_memory32->address,
-                       fixed_memory32->address_length,
-                       fixed_memory32->write_protect, 0);
-               break;
-       case ACPI_RESOURCE_TYPE_ADDRESS16:
-       case ACPI_RESOURCE_TYPE_ADDRESS32:
-       case ACPI_RESOURCE_TYPE_ADDRESS64:
-               pnpacpi_parse_allocated_address_space(dev, res);
-               break;
-
-       case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
-               pnpacpi_parse_allocated_ext_address_space(dev, res);
-               break;
-
-       case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
-               extended_irq = &res->data.extended_irq;
-
-               if (extended_irq->interrupt_count == 0)
-                       pnp_add_irq_resource(dev, 0, IORESOURCE_DISABLED);
-               else {
-                       for (i = 0; i < extended_irq->interrupt_count; i++) {
-                               pnpacpi_parse_allocated_irqresource(dev,
-                                       extended_irq->interrupts[i],
-                                       extended_irq->triggering,
-                                       extended_irq->polarity,
-                                       extended_irq->sharable);
-                       }
-
-                       /*
-                        * The IRQ encoder puts a single interrupt in each
-                        * descriptor, so if a _CRS descriptor has more than
-                        * one interrupt, we won't be able to re-encode it.
-                        */
-                       if (pnp_can_write(dev) &&
-                           extended_irq->interrupt_count > 1) {
-                               dev_warn(&dev->dev, "multiple interrupts in "
-                                        "_CRS descriptor; configuration can't "
-                                        "be changed\n");
-                               dev->capabilities &= ~PNP_WRITE;
-                       }
-               }
-               break;
-
        case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
                break;
 
@@ -531,7 +299,7 @@ static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev,
                if (p->interrupts[i])
                        __set_bit(p->interrupts[i], map.bits);
 
-       flags = irq_flags(p->triggering, p->polarity, p->sharable);
+       flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->sharable);
        pnp_register_irq_resource(dev, option_flags, &map, flags);
 }
 
@@ -555,7 +323,7 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev,
                }
        }
 
-       flags = irq_flags(p->triggering, p->polarity, p->sharable);
+       flags = acpi_dev_irq_flags(p->triggering, p->polarity, p->sharable);
        pnp_register_irq_resource(dev, option_flags, &map, flags);
 }
 
index b0ecacb..3e6db1c 100644 (file)
@@ -503,6 +503,22 @@ static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev)
        return pnp_res;
 }
 
+struct pnp_resource *pnp_add_resource(struct pnp_dev *dev,
+                                     struct resource *res)
+{
+       struct pnp_resource *pnp_res;
+
+       pnp_res = pnp_new_resource(dev);
+       if (!pnp_res) {
+               dev_err(&dev->dev, "can't add resource %pR\n", res);
+               return NULL;
+       }
+
+       pnp_res->res = *res;
+       dev_dbg(&dev->dev, "%pR\n", res);
+       return pnp_res;
+}
+
 struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
                                          int flags)
 {
index c17ae22..0c6fcb4 100644 (file)
@@ -401,7 +401,7 @@ EXPORT_SYMBOL_GPL(rio_release_inb_pwrite);
 /**
  * rio_map_inb_region -- Map inbound memory region.
  * @mport: Master port.
- * @lstart: physical address of memory region to be mapped
+ * @local: physical address of memory region to be mapped
  * @rbase: RIO base address assigned to this window
  * @size: Size of the memory region
  * @rflags: Flags for mapping.
index 5c4829c..e872c8b 100644 (file)
@@ -1381,22 +1381,14 @@ struct regulator *regulator_get_exclusive(struct device *dev, const char *id)
 }
 EXPORT_SYMBOL_GPL(regulator_get_exclusive);
 
-/**
- * regulator_put - "free" the regulator source
- * @regulator: regulator source
- *
- * Note: drivers must ensure that all regulator_enable calls made on this
- * regulator source are balanced by regulator_disable calls prior to calling
- * this function.
- */
-void regulator_put(struct regulator *regulator)
+/* Locks held by regulator_put() */
+static void _regulator_put(struct regulator *regulator)
 {
        struct regulator_dev *rdev;
 
        if (regulator == NULL || IS_ERR(regulator))
                return;
 
-       mutex_lock(&regulator_list_mutex);
        rdev = regulator->rdev;
 
        debugfs_remove_recursive(regulator->debugfs);
@@ -1412,6 +1404,20 @@ void regulator_put(struct regulator *regulator)
        rdev->exclusive = 0;
 
        module_put(rdev->owner);
+}
+
+/**
+ * regulator_put - "free" the regulator source
+ * @regulator: regulator source
+ *
+ * Note: drivers must ensure that all regulator_enable calls made on this
+ * regulator source are balanced by regulator_disable calls prior to calling
+ * this function.
+ */
+void regulator_put(struct regulator *regulator)
+{
+       mutex_lock(&regulator_list_mutex);
+       _regulator_put(regulator);
        mutex_unlock(&regulator_list_mutex);
 }
 EXPORT_SYMBOL_GPL(regulator_put);
@@ -1974,7 +1980,7 @@ int regulator_is_supported_voltage(struct regulator *regulator,
        if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {
                ret = regulator_get_voltage(regulator);
                if (ret >= 0)
-                       return (min_uV >= ret && ret <= max_uV);
+                       return (min_uV <= ret && ret <= max_uV);
                else
                        return ret;
        }
@@ -3365,7 +3371,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
                if (ret != 0) {
                        rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
                                 config->ena_gpio, ret);
-                       goto clean;
+                       goto wash;
                }
 
                rdev->ena_gpio = config->ena_gpio;
@@ -3445,10 +3451,11 @@ unset_supplies:
 
 scrub:
        if (rdev->supply)
-               regulator_put(rdev->supply);
+               _regulator_put(rdev->supply);
        if (rdev->ena_gpio)
                gpio_free(rdev->ena_gpio);
        kfree(rdev->constraints);
+wash:
        device_unregister(&rdev->dev);
        /* device core frees rdev */
        rdev = ERR_PTR(ret);
index e7a4780..9e198e5 100644 (file)
@@ -120,15 +120,11 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
        return vq;
 }
 
-static void rproc_virtio_del_vqs(struct virtio_device *vdev)
+static void __rproc_virtio_del_vqs(struct virtio_device *vdev)
 {
        struct virtqueue *vq, *n;
-       struct rproc *rproc = vdev_to_rproc(vdev);
        struct rproc_vring *rvring;
 
-       /* power down the remote processor before deleting vqs */
-       rproc_shutdown(rproc);
-
        list_for_each_entry_safe(vq, n, &vdev->vqs, list) {
                rvring = vq->priv;
                rvring->vq = NULL;
@@ -137,6 +133,16 @@ static void rproc_virtio_del_vqs(struct virtio_device *vdev)
        }
 }
 
+static void rproc_virtio_del_vqs(struct virtio_device *vdev)
+{
+       struct rproc *rproc = vdev_to_rproc(vdev);
+
+       /* power down the remote processor before deleting vqs */
+       rproc_shutdown(rproc);
+
+       __rproc_virtio_del_vqs(vdev);
+}
+
 static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
                       struct virtqueue *vqs[],
                       vq_callback_t *callbacks[],
@@ -163,7 +169,7 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
        return 0;
 
 error:
-       rproc_virtio_del_vqs(vdev);
+       __rproc_virtio_del_vqs(vdev);
        return ret;
 }
 
index 891cd6c..4eed510 100644 (file)
@@ -392,6 +392,8 @@ static int dryice_rtc_probe(struct platform_device *pdev)
        if (imxdi->ioaddr == NULL)
                return -ENOMEM;
 
+       spin_lock_init(&imxdi->irq_lock);
+
        imxdi->irq = platform_get_irq(pdev, 0);
        if (imxdi->irq < 0)
                return imxdi->irq;
index 7a82337..073108d 100644 (file)
@@ -288,11 +288,11 @@ static int __devinit tps65910_rtc_probe(struct platform_device *pdev)
 static int __devexit tps65910_rtc_remove(struct platform_device *pdev)
 {
        /* leave rtc running, but disable irqs */
-       struct rtc_device *rtc = platform_get_drvdata(pdev);
+       struct tps65910_rtc *tps_rtc = platform_get_drvdata(pdev);
 
-       tps65910_rtc_alarm_irq_enable(&rtc->dev, 0);
+       tps65910_rtc_alarm_irq_enable(&pdev->dev, 0);
 
-       rtc_device_unregister(rtc);
+       rtc_device_unregister(tps_rtc->rtc);
        return 0;
 }
 
index 9ffb6d5..4ed343e 100644 (file)
@@ -44,7 +44,6 @@
 #define RAW3215_NR_CCWS            3
 #define RAW3215_TIMEOUT            HZ/10     /* time for delayed output */
 
-#define RAW3215_FIXED      1         /* 3215 console device is not be freed */
 #define RAW3215_WORKING            4         /* set if a request is being worked on */
 #define RAW3215_THROTTLED   8        /* set if reading is disabled */
 #define RAW3215_STOPPED            16        /* set if writing is disabled */
@@ -339,8 +338,10 @@ static void raw3215_wakeup(unsigned long data)
        struct tty_struct *tty;
 
        tty = tty_port_tty_get(&raw->port);
-       tty_wakeup(tty);
-       tty_kref_put(tty);
+       if (tty) {
+               tty_wakeup(tty);
+               tty_kref_put(tty);
+       }
 }
 
 /*
@@ -629,8 +630,7 @@ static void raw3215_shutdown(struct raw3215_info *raw)
        DECLARE_WAITQUEUE(wait, current);
        unsigned long flags;
 
-       if (!(raw->port.flags & ASYNC_INITIALIZED) ||
-                       (raw->flags & RAW3215_FIXED))
+       if (!(raw->port.flags & ASYNC_INITIALIZED))
                return;
        /* Wait for outstanding requests, then free irq */
        spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
@@ -926,8 +926,6 @@ static int __init con3215_init(void)
        dev_set_drvdata(&cdev->dev, raw);
        cdev->handler = raw3215_irq;
 
-       raw->flags |= RAW3215_FIXED;
-
        /* Request the console irq */
        if (raw3215_startup(raw) != 0) {
                raw3215_free_info(raw);
index b4d572f..fd00afd 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 33bb4d8..4af3dfe 100644 (file)
@@ -112,9 +112,6 @@ extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);
 extern void css_reiterate_subchannels(void);
 void css_update_ssd_info(struct subchannel *sch);
 
-#define __MAX_SUBCHANNEL 65535
-#define __MAX_SSID 3
-
 struct channel_subsystem {
        u8 cssid;
        int valid;
index fc916f5..fd3143c 100644 (file)
@@ -1424,7 +1424,7 @@ static enum io_sch_action sch_get_action(struct subchannel *sch)
        }
        if (device_is_disconnected(cdev))
                return IO_SCH_REPROBE;
-       if (cdev->online)
+       if (cdev->online && !cdev->private->flags.resuming)
                return IO_SCH_VERIFY;
        if (cdev->private->state == DEV_STATE_NOT_OPER)
                return IO_SCH_UNREG_ATTACH;
@@ -1469,12 +1469,6 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
                rc = 0;
                goto out_unlock;
        case IO_SCH_VERIFY:
-               if (cdev->private->flags.resuming == 1) {
-                       if (cio_enable_subchannel(sch, (u32)(addr_t)sch)) {
-                               ccw_device_set_notoper(cdev);
-                               break;
-                       }
-               }
                /* Trigger path verification. */
                io_subchannel_verify(sch);
                rc = 0;
index e6d5f8c..65d13e3 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,12 @@ 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(to->num_ssid * to->num_id, 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 3d943f0..06d3bc0 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 3e25d31..4d6ba00 100644 (file)
@@ -2942,13 +2942,33 @@ static int qeth_query_ipassists_cb(struct qeth_card *card,
        QETH_DBF_TEXT(SETUP, 2, "qipasscb");
 
        cmd = (struct qeth_ipa_cmd *) data;
+
+       switch (cmd->hdr.return_code) {
+       case IPA_RC_NOTSUPP:
+       case IPA_RC_L2_UNSUPPORTED_CMD:
+               QETH_DBF_TEXT(SETUP, 2, "ipaunsup");
+               card->options.ipa4.supported_funcs |= IPA_SETADAPTERPARMS;
+               card->options.ipa6.supported_funcs |= IPA_SETADAPTERPARMS;
+               return -0;
+       default:
+               if (cmd->hdr.return_code) {
+                       QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Unhandled "
+                                               "rc=%d\n",
+                                               dev_name(&card->gdev->dev),
+                                               cmd->hdr.return_code);
+                       return 0;
+               }
+       }
+
        if (cmd->hdr.prot_version == QETH_PROT_IPV4) {
                card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported;
                card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
-       } else {
+       } else if (cmd->hdr.prot_version == QETH_PROT_IPV6) {
                card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported;
                card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
-       }
+       } else
+               QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Flawed LIC detected"
+                                       "\n", dev_name(&card->gdev->dev));
        QETH_DBF_TEXT(SETUP, 2, "suppenbl");
        QETH_DBF_TEXT_(SETUP, 2, "%08x", (__u32)cmd->hdr.ipa_supported);
        QETH_DBF_TEXT_(SETUP, 2, "%08x", (__u32)cmd->hdr.ipa_enabled);
index 2db4093..fddb626 100644 (file)
@@ -626,10 +626,13 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card)
        QETH_DBF_TEXT(SETUP, 2, "doL2init");
        QETH_DBF_TEXT_(SETUP, 2, "doL2%s", CARD_BUS_ID(card));
 
-       rc = qeth_query_setadapterparms(card);
-       if (rc) {
-               QETH_DBF_MESSAGE(2, "could not query adapter parameters on "
-                       "device %s: x%x\n", CARD_BUS_ID(card), rc);
+       if (qeth_is_supported(card, IPA_SETADAPTERPARMS)) {
+               rc = qeth_query_setadapterparms(card);
+               if (rc) {
+                       QETH_DBF_MESSAGE(2, "could not query adapter "
+                               "parameters on device %s: x%x\n",
+                               CARD_BUS_ID(card), rc);
+               }
        }
 
        if (card->info.type == QETH_CARD_TYPE_IQD ||
@@ -676,7 +679,7 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
                return -ERESTARTSYS;
        }
        rc = qeth_l2_send_delmac(card, &card->dev->dev_addr[0]);
-       if (!rc)
+       if (!rc || (rc == IPA_RC_L2_MAC_NOT_FOUND))
                rc = qeth_l2_send_setmac(card, addr->sa_data);
        return rc ? -EINVAL : 0;
 }
@@ -1141,11 +1144,12 @@ static int qeth_l2_recover(void *ptr)
                dev_info(&card->gdev->dev,
                        "Device successfully recovered!\n");
        else {
-               rtnl_lock();
-               dev_close(card->dev);
-               rtnl_unlock();
-               dev_warn(&card->gdev->dev, "The qeth device driver "
-                       "failed to recover an error on the device\n");
+               if (rtnl_trylock()) {
+                       dev_close(card->dev);
+                       rtnl_unlock();
+                       dev_warn(&card->gdev->dev, "The qeth device driver "
+                               "failed to recover an error on the device\n");
+               }
        }
        qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
        qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
index 4cd310c..5ba3906 100644 (file)
@@ -3510,11 +3510,12 @@ static int qeth_l3_recover(void *ptr)
                dev_info(&card->gdev->dev,
                        "Device successfully recovered!\n");
        else {
-               rtnl_lock();
-               dev_close(card->dev);
-               rtnl_unlock();
-               dev_warn(&card->gdev->dev, "The qeth device driver "
-                       "failed to recover an error on the device\n");
+               if (rtnl_trylock()) {
+                       dev_close(card->dev);
+                       rtnl_unlock();
+                       dev_warn(&card->gdev->dev, "The qeth device driver "
+                               "failed to recover an error on the device\n");
+               }
        }
        qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
        qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
index 207b7d7..d8f990b 100644 (file)
@@ -157,7 +157,7 @@ static int smsg_pm_restore_thaw(struct device *dev)
 #ifdef CONFIG_PM_DEBUG
        printk(KERN_WARNING "smsg_pm_restore_thaw\n");
 #endif
-       if (smsg_path && iucv_path_connected) {
+       if (smsg_path && !iucv_path_connected) {
                memset(smsg_path, 0, sizeof(*smsg_path));
                smsg_path->msglim = 255;
                smsg_path->flags = 0;
index 6206a66..737554c 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 d25f944..fc6a5aa 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 c1bafc3..9594ab6 100644 (file)
@@ -1972,7 +1972,7 @@ sci_io_request_frame_handler(struct isci_request *ireq,
                                                                      frame_index,
                                                                      (void **)&frame_buffer);
 
-                       sci_controller_copy_sata_response(&ireq->stp.req,
+                       sci_controller_copy_sata_response(&ireq->stp.rsp,
                                                               frame_header,
                                                               frame_buffer);
 
index 16b7a72..3b2365c 100644 (file)
@@ -1276,7 +1276,7 @@ struct megasas_evt_detail {
 } __attribute__ ((packed));
 
 struct megasas_aen_event {
-       struct work_struct hotplug_work;
+       struct delayed_work hotplug_work;
        struct megasas_instance *instance;
 };
 
index d2c5366..e4f2baa 100644 (file)
@@ -2060,9 +2060,9 @@ megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
                } else {
                        ev->instance = instance;
                        instance->ev = ev;
-                       INIT_WORK(&ev->hotplug_work, megasas_aen_polling);
-                       schedule_delayed_work(
-                               (struct delayed_work *)&ev->hotplug_work, 0);
+                       INIT_DELAYED_WORK(&ev->hotplug_work,
+                                         megasas_aen_polling);
+                       schedule_delayed_work(&ev->hotplug_work, 0);
                }
        }
 }
@@ -4352,8 +4352,7 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
        /* cancel the delayed work if this work still in queue */
        if (instance->ev != NULL) {
                struct megasas_aen_event *ev = instance->ev;
-               cancel_delayed_work_sync(
-                       (struct delayed_work *)&ev->hotplug_work);
+               cancel_delayed_work_sync(&ev->hotplug_work);
                instance->ev = NULL;
        }
 
@@ -4545,8 +4544,7 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
        /* cancel the delayed work if this work still in queue*/
        if (instance->ev != NULL) {
                struct megasas_aen_event *ev = instance->ev;
-               cancel_delayed_work_sync(
-                       (struct delayed_work *)&ev->hotplug_work);
+               cancel_delayed_work_sync(&ev->hotplug_work);
                instance->ev = NULL;
        }
 
@@ -5190,7 +5188,7 @@ static void
 megasas_aen_polling(struct work_struct *work)
 {
        struct megasas_aen_event *ev =
-               container_of(work, struct megasas_aen_event, hotplug_work);
+               container_of(work, struct megasas_aen_event, hotplug_work.work);
        struct megasas_instance *instance = ev->instance;
        union megasas_evt_class_locale class_locale;
        struct  Scsi_Host *host;
index bd4708a..20fd974 100644 (file)
@@ -149,6 +149,7 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha)
 int
 qla24xx_disable_vp(scsi_qla_host_t *vha)
 {
+       unsigned long flags;
        int ret;
 
        ret = qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL);
@@ -156,7 +157,9 @@ qla24xx_disable_vp(scsi_qla_host_t *vha)
        atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
 
        /* Remove port id from vp target map */
+       spin_lock_irqsave(&vha->hw->vport_slock, flags);
        qlt_update_vp_map(vha, RESET_AL_PA);
+       spin_unlock_irqrestore(&vha->hw->vport_slock, flags);
 
        qla2x00_mark_vp_devices_dead(vha);
        atomic_set(&vha->vp_state, VP_FAILED);
index 0e09d8f..62aa558 100644 (file)
@@ -557,6 +557,7 @@ static bool qlt_check_fcport_exist(struct scsi_qla_host *vha,
        int pmap_len;
        fc_port_t *fcport;
        int global_resets;
+       unsigned long flags;
 
 retry:
        global_resets = atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count);
@@ -625,10 +626,10 @@ retry:
            sess->s_id.b.area, sess->loop_id, fcport->d_id.b.domain,
            fcport->d_id.b.al_pa, fcport->d_id.b.area, fcport->loop_id);
 
-       sess->s_id = fcport->d_id;
-       sess->loop_id = fcport->loop_id;
-       sess->conf_compl_supported = !!(fcport->flags &
-           FCF_CONF_COMP_SUPPORTED);
+       spin_lock_irqsave(&ha->hardware_lock, flags);
+       ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
+                               (fcport->flags & FCF_CONF_COMP_SUPPORTED));
+       spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
        res = true;
 
@@ -740,10 +741,9 @@ static struct qla_tgt_sess *qlt_create_sess(
                                qlt_undelete_sess(sess);
 
                        kref_get(&sess->se_sess->sess_kref);
-                       sess->s_id = fcport->d_id;
-                       sess->loop_id = fcport->loop_id;
-                       sess->conf_compl_supported = !!(fcport->flags &
-                           FCF_CONF_COMP_SUPPORTED);
+                       ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
+                                               (fcport->flags & FCF_CONF_COMP_SUPPORTED));
+
                        if (sess->local && !local)
                                sess->local = 0;
                        spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -796,8 +796,7 @@ static struct qla_tgt_sess *qlt_create_sess(
         */
        kref_get(&sess->se_sess->sess_kref);
 
-       sess->conf_compl_supported = !!(fcport->flags &
-           FCF_CONF_COMP_SUPPORTED);
+       sess->conf_compl_supported = (fcport->flags & FCF_CONF_COMP_SUPPORTED);
        BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name));
        memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name));
 
@@ -869,10 +868,8 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
                        ql_dbg(ql_dbg_tgt_mgt, vha, 0xf007,
                            "Reappeared sess %p\n", sess);
                }
-               sess->s_id = fcport->d_id;
-               sess->loop_id = fcport->loop_id;
-               sess->conf_compl_supported = !!(fcport->flags &
-                   FCF_CONF_COMP_SUPPORTED);
+               ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
+                                       (fcport->flags & FCF_CONF_COMP_SUPPORTED));
        }
 
        if (sess && sess->local) {
index 170af15..bad7495 100644 (file)
@@ -648,6 +648,7 @@ struct qla_tgt_func_tmpl {
 
        int (*check_initiator_node_acl)(struct scsi_qla_host *, unsigned char *,
                                        void *, uint8_t *, uint16_t);
+       void (*update_sess)(struct qla_tgt_sess *, port_id_t, uint16_t, bool);
        struct qla_tgt_sess *(*find_sess_by_loop_id)(struct scsi_qla_host *,
                                                const uint16_t);
        struct qla_tgt_sess *(*find_sess_by_s_id)(struct scsi_qla_host *,
index 2358c16..3d74f2f 100644 (file)
@@ -237,7 +237,7 @@ static char *tcm_qla2xxx_get_fabric_wwn(struct se_portal_group *se_tpg)
                                struct tcm_qla2xxx_tpg, se_tpg);
        struct tcm_qla2xxx_lport *lport = tpg->lport;
 
-       return &lport->lport_name[0];
+       return lport->lport_naa_name;
 }
 
 static char *tcm_qla2xxx_npiv_get_fabric_wwn(struct se_portal_group *se_tpg)
@@ -1457,6 +1457,78 @@ static int tcm_qla2xxx_check_initiator_node_acl(
        return 0;
 }
 
+static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id,
+                                   uint16_t loop_id, bool conf_compl_supported)
+{
+       struct qla_tgt *tgt = sess->tgt;
+       struct qla_hw_data *ha = tgt->ha;
+       struct tcm_qla2xxx_lport *lport = ha->tgt.target_lport_ptr;
+       struct se_node_acl *se_nacl = sess->se_sess->se_node_acl;
+       struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl,
+                       struct tcm_qla2xxx_nacl, se_node_acl);
+       u32 key;
+
+
+       if (sess->loop_id != loop_id || sess->s_id.b24 != s_id.b24)
+               pr_info("Updating session %p from port %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x loop_id %d -> %d s_id %x:%x:%x -> %x:%x:%x\n",
+                       sess,
+                       sess->port_name[0], sess->port_name[1],
+                       sess->port_name[2], sess->port_name[3],
+                       sess->port_name[4], sess->port_name[5],
+                       sess->port_name[6], sess->port_name[7],
+                       sess->loop_id, loop_id,
+                       sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa,
+                       s_id.b.domain, s_id.b.area, s_id.b.al_pa);
+
+       if (sess->loop_id != loop_id) {
+               /*
+                * Because we can shuffle loop IDs around and we
+                * update different sessions non-atomically, we might
+                * have overwritten this session's old loop ID
+                * already, and we might end up overwriting some other
+                * session that will be updated later.  So we have to
+                * be extra careful and we can't warn about those things...
+                */
+               if (lport->lport_loopid_map[sess->loop_id].se_nacl == se_nacl)
+                       lport->lport_loopid_map[sess->loop_id].se_nacl = NULL;
+
+               lport->lport_loopid_map[loop_id].se_nacl = se_nacl;
+
+               sess->loop_id = loop_id;
+       }
+
+       if (sess->s_id.b24 != s_id.b24) {
+               key = (((u32) sess->s_id.b.domain << 16) |
+                      ((u32) sess->s_id.b.area   <<  8) |
+                      ((u32) sess->s_id.b.al_pa));
+
+               if (btree_lookup32(&lport->lport_fcport_map, key))
+                       WARN(btree_remove32(&lport->lport_fcport_map, key) != se_nacl,
+                            "Found wrong se_nacl when updating s_id %x:%x:%x\n",
+                            sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa);
+               else
+                       WARN(1, "No lport_fcport_map entry for s_id %x:%x:%x\n",
+                            sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa);
+
+               key = (((u32) s_id.b.domain << 16) |
+                      ((u32) s_id.b.area   <<  8) |
+                      ((u32) s_id.b.al_pa));
+
+               if (btree_lookup32(&lport->lport_fcport_map, key)) {
+                       WARN(1, "Already have lport_fcport_map entry for s_id %x:%x:%x\n",
+                            s_id.b.domain, s_id.b.area, s_id.b.al_pa);
+                       btree_update32(&lport->lport_fcport_map, key, se_nacl);
+               } else {
+                       btree_insert32(&lport->lport_fcport_map, key, se_nacl, GFP_ATOMIC);
+               }
+
+               sess->s_id = s_id;
+               nacl->nport_id = key;
+       }
+
+       sess->conf_compl_supported = conf_compl_supported;
+}
+
 /*
  * Calls into tcm_qla2xxx used by qla2xxx LLD I/O path.
  */
@@ -1467,6 +1539,7 @@ static struct qla_tgt_func_tmpl tcm_qla2xxx_template = {
        .free_cmd               = tcm_qla2xxx_free_cmd,
        .free_mcmd              = tcm_qla2xxx_free_mcmd,
        .free_session           = tcm_qla2xxx_free_session,
+       .update_sess            = tcm_qla2xxx_update_sess,
        .check_initiator_node_acl = tcm_qla2xxx_check_initiator_node_acl,
        .find_sess_by_s_id      = tcm_qla2xxx_find_sess_by_s_id,
        .find_sess_by_loop_id   = tcm_qla2xxx_find_sess_by_loop_id,
@@ -1534,6 +1607,7 @@ static struct se_wwn *tcm_qla2xxx_make_lport(
        lport->lport_wwpn = wwpn;
        tcm_qla2xxx_format_wwn(&lport->lport_name[0], TCM_QLA2XXX_NAMELEN,
                                wwpn);
+       sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) wwpn);
 
        ret = tcm_qla2xxx_init_lport(lport);
        if (ret != 0)
@@ -1601,6 +1675,7 @@ static struct se_wwn *tcm_qla2xxx_npiv_make_lport(
        lport->lport_npiv_wwnn = npiv_wwnn;
        tcm_qla2xxx_npiv_format_wwn(&lport->lport_npiv_name[0],
                        TCM_QLA2XXX_NAMELEN, npiv_wwpn, npiv_wwnn);
+       sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) npiv_wwpn);
 
 /* FIXME: tcm_qla2xxx_npiv_make_lport */
        ret = -ENOSYS;
index 8254981..9ba075f 100644 (file)
@@ -61,6 +61,8 @@ struct tcm_qla2xxx_lport {
        u64 lport_npiv_wwnn;
        /* ASCII formatted WWPN for FC Target Lport */
        char lport_name[TCM_QLA2XXX_NAMELEN];
+       /* ASCII formatted naa WWPN for VPD page 83 etc */
+       char lport_naa_name[TCM_QLA2XXX_NAMELEN];
        /* ASCII formatted WWPN+WWNN for NPIV FC Target Lport */
        char lport_npiv_name[TCM_QLA2XXX_NPIV_NAMELEN];
        /* map for fc_port pointers in 24-bit FC Port ID space */
index b191dd5..71fddbc 100644 (file)
@@ -1294,26 +1294,19 @@ static struct scsi_host_template qpti_template = {
 static const struct of_device_id qpti_match[];
 static int __devinit qpti_sbus_probe(struct platform_device *op)
 {
-       const struct of_device_id *match;
-       struct scsi_host_template *tpnt;
        struct device_node *dp = op->dev.of_node;
        struct Scsi_Host *host;
        struct qlogicpti *qpti;
        static int nqptis;
        const char *fcode;
 
-       match = of_match_device(qpti_match, &op->dev);
-       if (!match)
-               return -EINVAL;
-       tpnt = match->data;
-
        /* Sometimes Antares cards come up not completely
         * setup, and we get a report of a zero IRQ.
         */
        if (op->archdata.irqs[0] == 0)
                return -ENODEV;
 
-       host = scsi_host_alloc(tpnt, sizeof(struct qlogicpti));
+       host = scsi_host_alloc(&qpti_template, sizeof(struct qlogicpti));
        if (!host)
                return -ENOMEM;
 
@@ -1445,19 +1438,15 @@ static int __devexit qpti_sbus_remove(struct platform_device *op)
 static const struct of_device_id qpti_match[] = {
        {
                .name = "ptisp",
-               .data = &qpti_template,
        },
        {
                .name = "PTI,ptisp",
-               .data = &qpti_template,
        },
        {
                .name = "QLGC,isp",
-               .data = &qpti_template,
        },
        {
                .name = "SUNW,isp",
-               .data = &qpti_template,
        },
        {},
 };
index 2936b44..2c0d0ec 100644 (file)
@@ -55,6 +55,7 @@
 #include <linux/cpu.h>
 #include <linux/mutex.h>
 #include <linux/async.h>
+#include <asm/unaligned.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -1062,6 +1063,50 @@ int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf,
 EXPORT_SYMBOL_GPL(scsi_get_vpd_page);
 
 /**
+ * scsi_report_opcode - Find out if a given command opcode is supported
+ * @sdev:      scsi device to query
+ * @buffer:    scratch buffer (must be at least 20 bytes long)
+ * @len:       length of buffer
+ * @opcode:    opcode for command to look up
+ *
+ * Uses the REPORT SUPPORTED OPERATION CODES to look up the given
+ * opcode. Returns 0 if RSOC fails or if the command opcode is
+ * unsupported. Returns 1 if the device claims to support the command.
+ */
+int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
+                      unsigned int len, unsigned char opcode)
+{
+       unsigned char cmd[16];
+       struct scsi_sense_hdr sshdr;
+       int result;
+
+       if (sdev->no_report_opcodes || sdev->scsi_level < SCSI_SPC_3)
+               return 0;
+
+       memset(cmd, 0, 16);
+       cmd[0] = MAINTENANCE_IN;
+       cmd[1] = MI_REPORT_SUPPORTED_OPERATION_CODES;
+       cmd[2] = 1;             /* One command format */
+       cmd[3] = opcode;
+       put_unaligned_be32(len, &cmd[6]);
+       memset(buffer, 0, len);
+
+       result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len,
+                                 &sshdr, 30 * HZ, 3, NULL);
+
+       if (result && scsi_sense_valid(&sshdr) &&
+           sshdr.sense_key == ILLEGAL_REQUEST &&
+           (sshdr.asc == 0x20 || sshdr.asc == 0x24) && sshdr.ascq == 0x00)
+               return 0;
+
+       if ((buffer[1] & 3) == 3) /* Command supported */
+               return 1;
+
+       return 0;
+}
+EXPORT_SYMBOL(scsi_report_opcode);
+
+/**
  * scsi_device_get  -  get an additional reference to a scsi_device
  * @sdev:      device to get a reference to
  *
index da36a3a..9032e91 100644 (file)
@@ -900,11 +900,23 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                                action = ACTION_FAIL;
                                error = -EILSEQ;
                        /* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */
-                       } else if ((sshdr.asc == 0x20 || sshdr.asc == 0x24) &&
-                                  (cmd->cmnd[0] == UNMAP ||
-                                   cmd->cmnd[0] == WRITE_SAME_16 ||
-                                   cmd->cmnd[0] == WRITE_SAME)) {
-                               description = "Discard failure";
+                       } else if (sshdr.asc == 0x20 || sshdr.asc == 0x24) {
+                               switch (cmd->cmnd[0]) {
+                               case UNMAP:
+                                       description = "Discard failure";
+                                       break;
+                               case WRITE_SAME:
+                               case WRITE_SAME_16:
+                                       if (cmd->cmnd[1] & 0x8)
+                                               description = "Discard failure";
+                                       else
+                                               description =
+                                                       "Write same failure";
+                                       break;
+                               default:
+                                       description = "Invalid command failure";
+                                       break;
+                               }
                                action = ACTION_FAIL;
                                error = -EREMOTEIO;
                        } else
index 12f6fdf..352bc77 100644 (file)
@@ -99,6 +99,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC);
 #endif
 
 static void sd_config_discard(struct scsi_disk *, unsigned int);
+static void sd_config_write_same(struct scsi_disk *);
 static int  sd_revalidate_disk(struct gendisk *);
 static void sd_unlock_native_capacity(struct gendisk *disk);
 static int  sd_probe(struct device *);
@@ -395,6 +396,45 @@ sd_store_max_medium_access_timeouts(struct device *dev,
        return err ? err : count;
 }
 
+static ssize_t
+sd_show_write_same_blocks(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       struct scsi_disk *sdkp = to_scsi_disk(dev);
+
+       return snprintf(buf, 20, "%u\n", sdkp->max_ws_blocks);
+}
+
+static ssize_t
+sd_store_write_same_blocks(struct device *dev, struct device_attribute *attr,
+                          const char *buf, size_t count)
+{
+       struct scsi_disk *sdkp = to_scsi_disk(dev);
+       struct scsi_device *sdp = sdkp->device;
+       unsigned long max;
+       int err;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EACCES;
+
+       if (sdp->type != TYPE_DISK)
+               return -EINVAL;
+
+       err = kstrtoul(buf, 10, &max);
+
+       if (err)
+               return err;
+
+       if (max == 0)
+               sdp->no_write_same = 1;
+       else if (max <= SD_MAX_WS16_BLOCKS)
+               sdkp->max_ws_blocks = max;
+
+       sd_config_write_same(sdkp);
+
+       return count;
+}
+
 static struct device_attribute sd_disk_attrs[] = {
        __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type,
               sd_store_cache_type),
@@ -410,6 +450,8 @@ static struct device_attribute sd_disk_attrs[] = {
        __ATTR(thin_provisioning, S_IRUGO, sd_show_thin_provisioning, NULL),
        __ATTR(provisioning_mode, S_IRUGO|S_IWUSR, sd_show_provisioning_mode,
               sd_store_provisioning_mode),
+       __ATTR(max_write_same_blocks, S_IRUGO|S_IWUSR,
+              sd_show_write_same_blocks, sd_store_write_same_blocks),
        __ATTR(max_medium_access_timeouts, S_IRUGO|S_IWUSR,
               sd_show_max_medium_access_timeouts,
               sd_store_max_medium_access_timeouts),
@@ -561,19 +603,23 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
                return;
 
        case SD_LBP_UNMAP:
-               max_blocks = min_not_zero(sdkp->max_unmap_blocks, 0xffffffff);
+               max_blocks = min_not_zero(sdkp->max_unmap_blocks,
+                                         (u32)SD_MAX_WS16_BLOCKS);
                break;
 
        case SD_LBP_WS16:
-               max_blocks = min_not_zero(sdkp->max_ws_blocks, 0xffffffff);
+               max_blocks = min_not_zero(sdkp->max_ws_blocks,
+                                         (u32)SD_MAX_WS16_BLOCKS);
                break;
 
        case SD_LBP_WS10:
-               max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff);
+               max_blocks = min_not_zero(sdkp->max_ws_blocks,
+                                         (u32)SD_MAX_WS10_BLOCKS);
                break;
 
        case SD_LBP_ZERO:
-               max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff);
+               max_blocks = min_not_zero(sdkp->max_ws_blocks,
+                                         (u32)SD_MAX_WS10_BLOCKS);
                q->limits.discard_zeroes_data = 1;
                break;
        }
@@ -583,29 +629,26 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
 }
 
 /**
- * scsi_setup_discard_cmnd - unmap blocks on thinly provisioned device
+ * sd_setup_discard_cmnd - unmap blocks on thinly provisioned device
  * @sdp: scsi device to operate one
  * @rq: Request to prepare
  *
  * Will issue either UNMAP or WRITE SAME(16) depending on preference
  * indicated by target device.
  **/
-static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
+static int sd_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
 {
        struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
-       struct bio *bio = rq->bio;
-       sector_t sector = bio->bi_sector;
-       unsigned int nr_sectors = bio_sectors(bio);
+       sector_t sector = blk_rq_pos(rq);
+       unsigned int nr_sectors = blk_rq_sectors(rq);
+       unsigned int nr_bytes = blk_rq_bytes(rq);
        unsigned int len;
        int ret;
        char *buf;
        struct page *page;
 
-       if (sdkp->device->sector_size == 4096) {
-               sector >>= 3;
-               nr_sectors >>= 3;
-       }
-
+       sector >>= ilog2(sdp->sector_size) - 9;
+       nr_sectors >>= ilog2(sdp->sector_size) - 9;
        rq->timeout = SD_TIMEOUT;
 
        memset(rq->cmd, 0, rq->cmd_len);
@@ -660,6 +703,7 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
        blk_add_request_payload(rq, page, len);
        ret = scsi_setup_blk_pc_cmnd(sdp, rq);
        rq->buffer = page_address(page);
+       rq->__data_len = nr_bytes;
 
 out:
        if (ret != BLKPREP_OK) {
@@ -669,6 +713,83 @@ out:
        return ret;
 }
 
+static void sd_config_write_same(struct scsi_disk *sdkp)
+{
+       struct request_queue *q = sdkp->disk->queue;
+       unsigned int logical_block_size = sdkp->device->sector_size;
+       unsigned int blocks = 0;
+
+       if (sdkp->device->no_write_same) {
+               sdkp->max_ws_blocks = 0;
+               goto out;
+       }
+
+       /* Some devices can not handle block counts above 0xffff despite
+        * supporting WRITE SAME(16). Consequently we default to 64k
+        * blocks per I/O unless the device explicitly advertises a
+        * bigger limit.
+        */
+       if (sdkp->max_ws_blocks == 0)
+               sdkp->max_ws_blocks = SD_MAX_WS10_BLOCKS;
+
+       if (sdkp->ws16 || sdkp->max_ws_blocks > SD_MAX_WS10_BLOCKS)
+               blocks = min_not_zero(sdkp->max_ws_blocks,
+                                     (u32)SD_MAX_WS16_BLOCKS);
+       else
+               blocks = min_not_zero(sdkp->max_ws_blocks,
+                                     (u32)SD_MAX_WS10_BLOCKS);
+
+out:
+       blk_queue_max_write_same_sectors(q, blocks * (logical_block_size >> 9));
+}
+
+/**
+ * sd_setup_write_same_cmnd - write the same data to multiple blocks
+ * @sdp: scsi device to operate one
+ * @rq: Request to prepare
+ *
+ * Will issue either WRITE SAME(10) or WRITE SAME(16) depending on
+ * preference indicated by target device.
+ **/
+static int sd_setup_write_same_cmnd(struct scsi_device *sdp, struct request *rq)
+{
+       struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
+       struct bio *bio = rq->bio;
+       sector_t sector = blk_rq_pos(rq);
+       unsigned int nr_sectors = blk_rq_sectors(rq);
+       unsigned int nr_bytes = blk_rq_bytes(rq);
+       int ret;
+
+       if (sdkp->device->no_write_same)
+               return BLKPREP_KILL;
+
+       BUG_ON(bio_offset(bio) || bio_iovec(bio)->bv_len != sdp->sector_size);
+
+       sector >>= ilog2(sdp->sector_size) - 9;
+       nr_sectors >>= ilog2(sdp->sector_size) - 9;
+
+       rq->__data_len = sdp->sector_size;
+       rq->timeout = SD_WRITE_SAME_TIMEOUT;
+       memset(rq->cmd, 0, rq->cmd_len);
+
+       if (sdkp->ws16 || sector > 0xffffffff || nr_sectors > 0xffff) {
+               rq->cmd_len = 16;
+               rq->cmd[0] = WRITE_SAME_16;
+               put_unaligned_be64(sector, &rq->cmd[2]);
+               put_unaligned_be32(nr_sectors, &rq->cmd[10]);
+       } else {
+               rq->cmd_len = 10;
+               rq->cmd[0] = WRITE_SAME;
+               put_unaligned_be32(sector, &rq->cmd[2]);
+               put_unaligned_be16(nr_sectors, &rq->cmd[7]);
+       }
+
+       ret = scsi_setup_blk_pc_cmnd(sdp, rq);
+       rq->__data_len = nr_bytes;
+
+       return ret;
+}
+
 static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq)
 {
        rq->timeout = SD_FLUSH_TIMEOUT;
@@ -712,7 +833,10 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
         * block PC requests to make life easier.
         */
        if (rq->cmd_flags & REQ_DISCARD) {
-               ret = scsi_setup_discard_cmnd(sdp, rq);
+               ret = sd_setup_discard_cmnd(sdp, rq);
+               goto out;
+       } else if (rq->cmd_flags & REQ_WRITE_SAME) {
+               ret = sd_setup_write_same_cmnd(sdp, rq);
                goto out;
        } else if (rq->cmd_flags & REQ_FLUSH) {
                ret = scsi_setup_flush_cmnd(sdp, rq);
@@ -1482,12 +1606,21 @@ static int sd_done(struct scsi_cmnd *SCpnt)
        unsigned int good_bytes = result ? 0 : scsi_bufflen(SCpnt);
        struct scsi_sense_hdr sshdr;
        struct scsi_disk *sdkp = scsi_disk(SCpnt->request->rq_disk);
+       struct request *req = SCpnt->request;
        int sense_valid = 0;
        int sense_deferred = 0;
        unsigned char op = SCpnt->cmnd[0];
+       unsigned char unmap = SCpnt->cmnd[1] & 8;
 
-       if ((SCpnt->request->cmd_flags & REQ_DISCARD) && !result)
-               scsi_set_resid(SCpnt, 0);
+       if (req->cmd_flags & REQ_DISCARD || req->cmd_flags & REQ_WRITE_SAME) {
+               if (!result) {
+                       good_bytes = blk_rq_bytes(req);
+                       scsi_set_resid(SCpnt, 0);
+               } else {
+                       good_bytes = 0;
+                       scsi_set_resid(SCpnt, blk_rq_bytes(req));
+               }
+       }
 
        if (result) {
                sense_valid = scsi_command_normalize_sense(SCpnt, &sshdr);
@@ -1536,9 +1669,25 @@ static int sd_done(struct scsi_cmnd *SCpnt)
                if (sshdr.asc == 0x10)  /* DIX: Host detected corruption */
                        good_bytes = sd_completed_bytes(SCpnt);
                /* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */
-               if ((sshdr.asc == 0x20 || sshdr.asc == 0x24) &&
-                   (op == UNMAP || op == WRITE_SAME_16 || op == WRITE_SAME))
-                       sd_config_discard(sdkp, SD_LBP_DISABLE);
+               if (sshdr.asc == 0x20 || sshdr.asc == 0x24) {
+                       switch (op) {
+                       case UNMAP:
+                               sd_config_discard(sdkp, SD_LBP_DISABLE);
+                               break;
+                       case WRITE_SAME_16:
+                       case WRITE_SAME:
+                               if (unmap)
+                                       sd_config_discard(sdkp, SD_LBP_DISABLE);
+                               else {
+                                       sdkp->device->no_write_same = 1;
+                                       sd_config_write_same(sdkp);
+
+                                       good_bytes = 0;
+                                       req->__data_len = blk_rq_bytes(req);
+                                       req->cmd_flags |= REQ_QUIET;
+                               }
+                       }
+               }
                break;
        default:
                break;
@@ -2374,9 +2523,7 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
        if (buffer[3] == 0x3c) {
                unsigned int lba_count, desc_count;
 
-               sdkp->max_ws_blocks =
-                       (u32) min_not_zero(get_unaligned_be64(&buffer[36]),
-                                          (u64)0xffffffff);
+               sdkp->max_ws_blocks = (u32)get_unaligned_be64(&buffer[36]);
 
                if (!sdkp->lbpme)
                        goto out;
@@ -2469,6 +2616,13 @@ static void sd_read_block_provisioning(struct scsi_disk *sdkp)
        kfree(buffer);
 }
 
+static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer)
+{
+       if (scsi_report_opcode(sdkp->device, buffer, SD_BUF_SIZE,
+                              WRITE_SAME_16))
+               sdkp->ws16 = 1;
+}
+
 static int sd_try_extended_inquiry(struct scsi_device *sdp)
 {
        /*
@@ -2528,6 +2682,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
                sd_read_write_protect_flag(sdkp, buffer);
                sd_read_cache_type(sdkp, buffer);
                sd_read_app_tag_own(sdkp, buffer);
+               sd_read_write_same(sdkp, buffer);
        }
 
        sdkp->first_scan = 0;
@@ -2545,6 +2700,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
        blk_queue_flush(sdkp->disk->queue, flush);
 
        set_capacity(disk, sdkp->capacity);
+       sd_config_write_same(sdkp);
        kfree(buffer);
 
  out:
index 47c52a6..74a1e4c 100644 (file)
@@ -14,6 +14,7 @@
 #define SD_TIMEOUT             (30 * HZ)
 #define SD_MOD_TIMEOUT         (75 * HZ)
 #define SD_FLUSH_TIMEOUT       (60 * HZ)
+#define SD_WRITE_SAME_TIMEOUT  (120 * HZ)
 
 /*
  * Number of allowed retries
@@ -39,6 +40,11 @@ enum {
 };
 
 enum {
+       SD_MAX_WS10_BLOCKS = 0xffff,
+       SD_MAX_WS16_BLOCKS = 0x7fffff,
+};
+
+enum {
        SD_LBP_FULL = 0,        /* Full logical block provisioning */
        SD_LBP_UNMAP,           /* Use UNMAP command */
        SD_LBP_WS16,            /* Use WRITE SAME(16) with UNMAP bit */
@@ -77,6 +83,7 @@ struct scsi_disk {
        unsigned        lbpws : 1;
        unsigned        lbpws10 : 1;
        unsigned        lbpvpd : 1;
+       unsigned        ws16 : 1;
 };
 #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
 
index f892ae1..114390f 100644 (file)
@@ -75,54 +75,61 @@ unsigned long intc_get_field_from_handle(unsigned int value, unsigned int handle
 static unsigned long test_8(unsigned long addr, unsigned long h,
                            unsigned long ignore)
 {
-       return intc_get_field_from_handle(__raw_readb(addr), h);
+       void __iomem *ptr = (void __iomem *)addr;
+       return intc_get_field_from_handle(__raw_readb(ptr), h);
 }
 
 static unsigned long test_16(unsigned long addr, unsigned long h,
                             unsigned long ignore)
 {
-       return intc_get_field_from_handle(__raw_readw(addr), h);
+       void __iomem *ptr = (void __iomem *)addr;
+       return intc_get_field_from_handle(__raw_readw(ptr), h);
 }
 
 static unsigned long test_32(unsigned long addr, unsigned long h,
                             unsigned long ignore)
 {
-       return intc_get_field_from_handle(__raw_readl(addr), h);
+       void __iomem *ptr = (void __iomem *)addr;
+       return intc_get_field_from_handle(__raw_readl(ptr), h);
 }
 
 static unsigned long write_8(unsigned long addr, unsigned long h,
                             unsigned long data)
 {
-       __raw_writeb(intc_set_field_from_handle(0, data, h), addr);
-       (void)__raw_readb(addr);        /* Defeat write posting */
+       void __iomem *ptr = (void __iomem *)addr;
+       __raw_writeb(intc_set_field_from_handle(0, data, h), ptr);
+       (void)__raw_readb(ptr); /* Defeat write posting */
        return 0;
 }
 
 static unsigned long write_16(unsigned long addr, unsigned long h,
                              unsigned long data)
 {
-       __raw_writew(intc_set_field_from_handle(0, data, h), addr);
-       (void)__raw_readw(addr);        /* Defeat write posting */
+       void __iomem *ptr = (void __iomem *)addr;
+       __raw_writew(intc_set_field_from_handle(0, data, h), ptr);
+       (void)__raw_readw(ptr); /* Defeat write posting */
        return 0;
 }
 
 static unsigned long write_32(unsigned long addr, unsigned long h,
                              unsigned long data)
 {
-       __raw_writel(intc_set_field_from_handle(0, data, h), addr);
-       (void)__raw_readl(addr);        /* Defeat write posting */
+       void __iomem *ptr = (void __iomem *)addr;
+       __raw_writel(intc_set_field_from_handle(0, data, h), ptr);
+       (void)__raw_readl(ptr); /* Defeat write posting */
        return 0;
 }
 
 static unsigned long modify_8(unsigned long addr, unsigned long h,
                              unsigned long data)
 {
+       void __iomem *ptr = (void __iomem *)addr;
        unsigned long flags;
        unsigned int value;
        local_irq_save(flags);
-       value = intc_set_field_from_handle(__raw_readb(addr), data, h);
-       __raw_writeb(value, addr);
-       (void)__raw_readb(addr);        /* Defeat write posting */
+       value = intc_set_field_from_handle(__raw_readb(ptr), data, h);
+       __raw_writeb(value, ptr);
+       (void)__raw_readb(ptr); /* Defeat write posting */
        local_irq_restore(flags);
        return 0;
 }
@@ -130,12 +137,13 @@ static unsigned long modify_8(unsigned long addr, unsigned long h,
 static unsigned long modify_16(unsigned long addr, unsigned long h,
                               unsigned long data)
 {
+       void __iomem *ptr = (void __iomem *)addr;
        unsigned long flags;
        unsigned int value;
        local_irq_save(flags);
-       value = intc_set_field_from_handle(__raw_readw(addr), data, h);
-       __raw_writew(value, addr);
-       (void)__raw_readw(addr);        /* Defeat write posting */
+       value = intc_set_field_from_handle(__raw_readw(ptr), data, h);
+       __raw_writew(value, ptr);
+       (void)__raw_readw(ptr); /* Defeat write posting */
        local_irq_restore(flags);
        return 0;
 }
@@ -143,12 +151,13 @@ static unsigned long modify_16(unsigned long addr, unsigned long h,
 static unsigned long modify_32(unsigned long addr, unsigned long h,
                               unsigned long data)
 {
+       void __iomem *ptr = (void __iomem *)addr;
        unsigned long flags;
        unsigned int value;
        local_irq_save(flags);
-       value = intc_set_field_from_handle(__raw_readl(addr), data, h);
-       __raw_writel(value, addr);
-       (void)__raw_readl(addr);        /* Defeat write posting */
+       value = intc_set_field_from_handle(__raw_readl(ptr), data, h);
+       __raw_writel(value, ptr);
+       (void)__raw_readl(ptr); /* Defeat write posting */
        local_irq_restore(flags);
        return 0;
 }
index 012df26..46427b4 100644 (file)
@@ -83,7 +83,7 @@ static void intc_mask_ack(struct irq_data *data)
        unsigned int irq = data->irq;
        struct intc_desc_int *d = get_intc_desc(irq);
        unsigned long handle = intc_get_ack_handle(irq);
-       unsigned long addr;
+       void __iomem *addr;
 
        intc_disable(data);
 
@@ -91,7 +91,7 @@ static void intc_mask_ack(struct irq_data *data)
        if (handle) {
                unsigned int value;
 
-               addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
+               addr = (void __iomem *)INTC_REG(d, _INTC_ADDR_D(handle), 0);
                value = intc_set_field_from_handle(0, 1, handle);
 
                switch (_INTC_FN(handle)) {
index edf1360..86dd04d 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 9194641..a1db91a 100644 (file)
@@ -2186,8 +2186,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);
@@ -2292,7 +2290,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);
index 4894bde..30faf6d 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 1a81c90..6e7a805 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;
 };
@@ -1067,11 +1067,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";
        }
 
index 84c2861..718cc1f 100644 (file)
@@ -35,6 +35,8 @@
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/kthread.h>
+#include <linux/ioport.h>
+#include <linux/acpi.h>
 
 static void spidev_release(struct device *dev)
 {
@@ -93,6 +95,10 @@ static int spi_match_device(struct device *dev, struct device_driver *drv)
        if (of_driver_match_device(dev, drv))
                return 1;
 
+       /* Then try ACPI */
+       if (acpi_driver_match_device(dev, drv))
+               return 1;
+
        if (sdrv->id_table)
                return !!spi_match_id(sdrv->id_table, spi);
 
@@ -819,7 +825,7 @@ static void of_register_spi_devices(struct spi_master *master)
        if (!master->dev.of_node)
                return;
 
-       for_each_child_of_node(master->dev.of_node, nc) {
+       for_each_available_child_of_node(master->dev.of_node, nc) {
                /* Alloc an spi_device */
                spi = spi_alloc_device(master);
                if (!spi) {
@@ -888,6 +894,100 @@ static void of_register_spi_devices(struct spi_master *master)
 static void of_register_spi_devices(struct spi_master *master) { }
 #endif
 
+#ifdef CONFIG_ACPI
+static int acpi_spi_add_resource(struct acpi_resource *ares, void *data)
+{
+       struct spi_device *spi = data;
+
+       if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
+               struct acpi_resource_spi_serialbus *sb;
+
+               sb = &ares->data.spi_serial_bus;
+               if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_SPI) {
+                       spi->chip_select = sb->device_selection;
+                       spi->max_speed_hz = sb->connection_speed;
+
+                       if (sb->clock_phase == ACPI_SPI_SECOND_PHASE)
+                               spi->mode |= SPI_CPHA;
+                       if (sb->clock_polarity == ACPI_SPI_START_HIGH)
+                               spi->mode |= SPI_CPOL;
+                       if (sb->device_polarity == ACPI_SPI_ACTIVE_HIGH)
+                               spi->mode |= SPI_CS_HIGH;
+               }
+       } else if (spi->irq < 0) {
+               struct resource r;
+
+               if (acpi_dev_resource_interrupt(ares, 0, &r))
+                       spi->irq = r.start;
+       }
+
+       /* Always tell the ACPI core to skip this resource */
+       return 1;
+}
+
+static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level,
+                                      void *data, void **return_value)
+{
+       struct spi_master *master = data;
+       struct list_head resource_list;
+       struct acpi_device *adev;
+       struct spi_device *spi;
+       int ret;
+
+       if (acpi_bus_get_device(handle, &adev))
+               return AE_OK;
+       if (acpi_bus_get_status(adev) || !adev->status.present)
+               return AE_OK;
+
+       spi = spi_alloc_device(master);
+       if (!spi) {
+               dev_err(&master->dev, "failed to allocate SPI device for %s\n",
+                       dev_name(&adev->dev));
+               return AE_NO_MEMORY;
+       }
+
+       ACPI_HANDLE_SET(&spi->dev, handle);
+       spi->irq = -1;
+
+       INIT_LIST_HEAD(&resource_list);
+       ret = acpi_dev_get_resources(adev, &resource_list,
+                                    acpi_spi_add_resource, spi);
+       acpi_dev_free_resource_list(&resource_list);
+
+       if (ret < 0 || !spi->max_speed_hz) {
+               spi_dev_put(spi);
+               return AE_OK;
+       }
+
+       strlcpy(spi->modalias, dev_name(&adev->dev), sizeof(spi->modalias));
+       if (spi_add_device(spi)) {
+               dev_err(&master->dev, "failed to add SPI device %s from ACPI\n",
+                       dev_name(&adev->dev));
+               spi_dev_put(spi);
+       }
+
+       return AE_OK;
+}
+
+static void acpi_register_spi_devices(struct spi_master *master)
+{
+       acpi_status status;
+       acpi_handle handle;
+
+       handle = ACPI_HANDLE(&master->dev);
+       if (!handle)
+               return;
+
+       status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
+                                    acpi_spi_add_device, NULL,
+                                    master, NULL);
+       if (ACPI_FAILURE(status))
+               dev_warn(&master->dev, "failed to enumerate SPI slaves\n");
+}
+#else
+static inline void acpi_register_spi_devices(struct spi_master *master) {}
+#endif /* CONFIG_ACPI */
+
 static void spi_master_release(struct device *dev)
 {
        struct spi_master *master;
@@ -1023,8 +1123,9 @@ int spi_register_master(struct spi_master *master)
                spi_match_master_to_boardinfo(master, &bi->board_info);
        mutex_unlock(&board_lock);
 
-       /* Register devices from the device tree */
+       /* Register devices from the device tree and ACPI */
        of_register_spi_devices(master);
+       acpi_register_spi_devices(master);
 done:
        return status;
 }
index f2ffd96..d0cafd6 100644 (file)
@@ -51,12 +51,10 @@ enum android_alarm_return_flags {
 #define ANDROID_ALARM_WAIT                  _IO('a', 1)
 
 #define ALARM_IOW(c, type, size)            _IOW('a', (c) | ((type) << 4), size)
-#define ALARM_IOR(c, type, size)            _IOR('a', (c) | ((type) << 4), size)
-
 /* Set alarm */
 #define ANDROID_ALARM_SET(type)             ALARM_IOW(2, type, struct timespec)
 #define ANDROID_ALARM_SET_AND_WAIT(type)    ALARM_IOW(3, type, struct timespec)
-#define ANDROID_ALARM_GET_TIME(type)        ALARM_IOR(4, type, struct timespec)
+#define ANDROID_ALARM_GET_TIME(type)        ALARM_IOW(4, type, struct timespec)
 #define ANDROID_ALARM_SET_RTC               _IOW('a', 5, struct timespec)
 #define ANDROID_ALARM_BASE_CMD(cmd)         (cmd & ~(_IOC(0, 0, 0xf0, 0)))
 #define ANDROID_ALARM_IOCTL_TO_TYPE(cmd)    (_IOC_NR(cmd) >> 4)
index 7b0ba92..5d4610b 100644 (file)
@@ -567,7 +567,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);
@@ -2419,14 +2419,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;
                }
        }
@@ -2899,6 +2923,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 +2962,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))) {
index 7dff3c0..d00aff6 100644 (file)
@@ -289,6 +289,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 08f3052..29eb52d 100644 (file)
@@ -1410,6 +1410,8 @@ static void dio200_detach(struct comedi_device *dev)
        const struct dio200_layout_struct *layout;
        unsigned n;
 
+       if (!thisboard)
+               return;
        if (dev->irq)
                free_irq(dev->irq, dev);
        if (dev->subdevices) {
index eacb5e4..4e4f3c1 100644 (file)
@@ -573,9 +573,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 60830cc..d0a4c44 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 5fd21fa..c304528 100644 (file)
@@ -846,6 +846,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 2ba0ade..68d7c6a 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 28b91a6..b5a19a0 100644 (file)
@@ -772,6 +772,8 @@ void labpc_common_detach(struct comedi_device *dev)
 {
        struct comedi_subdevice *s;
 
+       if (!thisboard)
+               return;
        if (dev->subdevices) {
                s = &dev->subdevices[2];
                subdev_8255_cleanup(dev, s);
index 268dcb9..4792d05 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 28f5c9a..24327c3 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 7d7de87..e125b03 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 8e37d6e..b12ca68 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) {
index 002fa9d..e7b3441 100644 (file)
@@ -316,25 +316,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 05bdb7c..c6234c2 100644 (file)
@@ -317,26 +317,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 +347,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:
index b7333bf..7ee974b 100644 (file)
@@ -343,28 +343,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) {
@@ -491,6 +492,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 c755089..eaadd9d 100644 (file)
@@ -486,7 +486,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 +495,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 0fc26a4..35e0939 100644 (file)
@@ -373,30 +373,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 9571c03..aa964a2 100644 (file)
@@ -498,28 +498,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) {
index d59d7ac..77c601d 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 b302c9b..3144a7b 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 */
@@ -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 bb8aa70..46d6657 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/slab.h>
 #include "tpci200.h"
 
 static u16 tpci200_status_timeout[] = {
index 3434e6e..66e2c2f 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;
index 843c541..3abf661 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 066a3ce..f619fb3 100644 (file)
@@ -126,7 +126,8 @@ static int mem_map_vmalloc(struct bridge_dev_context *dev_context,
                                  u32 ul_num_bytes,
                                  struct hw_mmu_map_attrs_t *hw_attrs);
 
-bool wait_for_start(struct bridge_dev_context *dev_context, u32 dw_sync_addr);
+bool wait_for_start(struct bridge_dev_context *dev_context,
+                       void __iomem *sync_addr);
 
 /*  ----------------------------------- Globals */
 
@@ -363,10 +364,11 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
 {
        int status = 0;
        struct bridge_dev_context *dev_context = dev_ctxt;
-       u32 dw_sync_addr = 0;
+       void __iomem *sync_addr;
        u32 ul_shm_base;        /* Gpp Phys SM base addr(byte) */
        u32 ul_shm_base_virt;   /* Dsp Virt SM base addr */
        u32 ul_tlb_base_virt;   /* Base of MMU TLB entry */
+       u32 shm_sync_pa;
        /* Offset of shm_base_virt from tlb_base_virt */
        u32 ul_shm_offset_virt;
        s32 entry_ndx;
@@ -397,15 +399,22 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
        /* Kernel logical address */
        ul_shm_base = dev_context->atlb_entry[0].gpp_va + ul_shm_offset_virt;
 
+       /* SHM physical sync address */
+       shm_sync_pa = dev_context->atlb_entry[0].gpp_pa + ul_shm_offset_virt +
+                       SHMSYNCOFFSET;
+
        /* 2nd wd is used as sync field */
-       dw_sync_addr = ul_shm_base + SHMSYNCOFFSET;
+       sync_addr = ioremap(shm_sync_pa, SZ_32);
+       if (!sync_addr)
+               return -ENOMEM;
+
        /* Write a signature into the shm base + offset; this will
         * get cleared when the DSP program starts. */
        if ((ul_shm_base_virt == 0) || (ul_shm_base == 0)) {
                pr_err("%s: Illegal SM base\n", __func__);
                status = -EPERM;
        } else
-               __raw_writel(0xffffffff, dw_sync_addr);
+               __raw_writel(0xffffffff, sync_addr);
 
        if (!status) {
                resources = dev_context->resources;
@@ -419,8 +428,10 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
                         * function is made available.
                         */
                        void __iomem *ctrl = ioremap(0x48002000, SZ_4K);
-                       if (!ctrl)
+                       if (!ctrl) {
+                               iounmap(sync_addr);
                                return -ENOMEM;
+                       }
 
                        (*pdata->dsp_prm_rmw_bits)(OMAP3430_RST1_IVA2_MASK,
                                        OMAP3430_RST1_IVA2_MASK, OMAP3430_IVA2_MOD,
@@ -588,15 +599,15 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
                (*pdata->dsp_prm_rmw_bits)(OMAP3430_RST1_IVA2_MASK, 0,
                                        OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
 
-               dev_dbg(bridge, "Waiting for Sync @ 0x%x\n", dw_sync_addr);
+               dev_dbg(bridge, "Waiting for Sync @ 0x%x\n", *(u32 *)sync_addr);
                dev_dbg(bridge, "DSP c_int00 Address =  0x%x\n", dsp_addr);
                if (dsp_debug)
-                       while (__raw_readw(dw_sync_addr))
+                       while (__raw_readw(sync_addr))
                                ;
 
                /* Wait for DSP to clear word in shared memory */
                /* Read the Location */
-               if (!wait_for_start(dev_context, dw_sync_addr))
+               if (!wait_for_start(dev_context, sync_addr))
                        status = -ETIMEDOUT;
 
                dev_get_symbol(dev_context->dev_obj, "_WDT_enable", &wdt_en);
@@ -612,7 +623,7 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
                        /* Write the synchronization bit to indicate the
                         * completion of OPP table update to DSP
                         */
-                       __raw_writel(0XCAFECAFE, dw_sync_addr);
+                       __raw_writel(0XCAFECAFE, sync_addr);
 
                        /* update board state */
                        dev_context->brd_state = BRD_RUNNING;
@@ -621,6 +632,9 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
                        dev_context->brd_state = BRD_UNKNOWN;
                }
        }
+
+       iounmap(sync_addr);
+
        return status;
 }
 
@@ -1796,12 +1810,13 @@ static int mem_map_vmalloc(struct bridge_dev_context *dev_context,
  *  ======== wait_for_start ========
  *      Wait for the singal from DSP that it has started, or time out.
  */
-bool wait_for_start(struct bridge_dev_context *dev_context, u32 dw_sync_addr)
+bool wait_for_start(struct bridge_dev_context *dev_context,
+                       void __iomem *sync_addr)
 {
        u16 timeout = TIHELEN_ACKTIMEOUT;
 
        /*  Wait for response from board */
-       while (__raw_readw(dw_sync_addr) && --timeout)
+       while (__raw_readw(sync_addr) && --timeout)
                udelay(10);
 
        /*  If timed out: return false */
index 71cb822..50244a4 100644 (file)
@@ -48,37 +48,12 @@ enum hw_mmu_page_size_t {
 };
 
 /*
- * FUNCTION          : mmu_flush_entry
- *
- * INPUTS:
- *
- *       Identifier      : base_address
- *       Type          : const u32
- *       Description     : Base Address of instance of MMU module
- *
- * RETURNS:
- *
- *       Type          : hw_status
- *       Description     : 0            -- No errors occurred
- *                      RET_BAD_NULL_PARAM     -- A Pointer
- *                                             Parameter was set to NULL
- *
- * PURPOSE:          : Flush the TLB entry pointed by the
- *                     lock counter register
- *                     even if this entry is set protected
- *
- * METHOD:            : Check the Input parameter and Flush a
- *                      single entry in the TLB.
- */
-static hw_status mmu_flush_entry(const void __iomem *base_address);
-
-/*
  * FUNCTION          : mmu_set_cam_entry
  *
  * INPUTS:
  *
  *       Identifier      : base_address
- *       TypE          : const u32
+ *       Type           : void __iomem *
  *       Description     : Base Address of instance of MMU module
  *
  *       Identifier      : page_sz
@@ -112,7 +87,7 @@ static hw_status mmu_flush_entry(const void __iomem *base_address);
  *
  * METHOD:             : Check the Input parameters and set the CAM entry.
  */
-static hw_status mmu_set_cam_entry(const void __iomem *base_address,
+static hw_status mmu_set_cam_entry(void __iomem *base_address,
                                   const u32 page_sz,
                                   const u32 preserved_bit,
                                   const u32 valid_bit,
@@ -124,7 +99,7 @@ static hw_status mmu_set_cam_entry(const void __iomem *base_address,
  * INPUTS:
  *
  *       Identifier      : base_address
- *       Type          : const u32
+ *       Type           : void __iomem *
  *       Description     : Base Address of instance of MMU module
  *
  *       Identifier      : physical_addr
@@ -157,7 +132,7 @@ static hw_status mmu_set_cam_entry(const void __iomem *base_address,
  *
  * METHOD:            : Check the Input parameters and set the RAM entry.
  */
-static hw_status mmu_set_ram_entry(const void __iomem *base_address,
+static hw_status mmu_set_ram_entry(void __iomem *base_address,
                                   const u32 physical_addr,
                                   enum hw_endianism_t endianism,
                                   enum hw_element_size_t element_size,
@@ -165,7 +140,7 @@ static hw_status mmu_set_ram_entry(const void __iomem *base_address,
 
 /* HW FUNCTIONS */
 
-hw_status hw_mmu_enable(const void __iomem *base_address)
+hw_status hw_mmu_enable(void __iomem *base_address)
 {
        hw_status status = 0;
 
@@ -174,7 +149,7 @@ hw_status hw_mmu_enable(const void __iomem *base_address)
        return status;
 }
 
-hw_status hw_mmu_disable(const void __iomem *base_address)
+hw_status hw_mmu_disable(void __iomem *base_address)
 {
        hw_status status = 0;
 
@@ -183,7 +158,7 @@ hw_status hw_mmu_disable(const void __iomem *base_address)
        return status;
 }
 
-hw_status hw_mmu_num_locked_set(const void __iomem *base_address,
+hw_status hw_mmu_num_locked_set(void __iomem *base_address,
                                u32 num_locked_entries)
 {
        hw_status status = 0;
@@ -193,7 +168,7 @@ hw_status hw_mmu_num_locked_set(const void __iomem *base_address,
        return status;
 }
 
-hw_status hw_mmu_victim_num_set(const void __iomem *base_address,
+hw_status hw_mmu_victim_num_set(void __iomem *base_address,
                                u32 victim_entry_num)
 {
        hw_status status = 0;
@@ -203,7 +178,7 @@ hw_status hw_mmu_victim_num_set(const void __iomem *base_address,
        return status;
 }
 
-hw_status hw_mmu_event_ack(const void __iomem *base_address, u32 irq_mask)
+hw_status hw_mmu_event_ack(void __iomem *base_address, u32 irq_mask)
 {
        hw_status status = 0;
 
@@ -212,7 +187,7 @@ hw_status hw_mmu_event_ack(const void __iomem *base_address, u32 irq_mask)
        return status;
 }
 
-hw_status hw_mmu_event_disable(const void __iomem *base_address, u32 irq_mask)
+hw_status hw_mmu_event_disable(void __iomem *base_address, u32 irq_mask)
 {
        hw_status status = 0;
        u32 irq_reg;
@@ -224,7 +199,7 @@ hw_status hw_mmu_event_disable(const void __iomem *base_address, u32 irq_mask)
        return status;
 }
 
-hw_status hw_mmu_event_enable(const void __iomem *base_address, u32 irq_mask)
+hw_status hw_mmu_event_enable(void __iomem *base_address, u32 irq_mask)
 {
        hw_status status = 0;
        u32 irq_reg;
@@ -236,7 +211,7 @@ hw_status hw_mmu_event_enable(const void __iomem *base_address, u32 irq_mask)
        return status;
 }
 
-hw_status hw_mmu_event_status(const void __iomem *base_address, u32 *irq_mask)
+hw_status hw_mmu_event_status(void __iomem *base_address, u32 *irq_mask)
 {
        hw_status status = 0;
 
@@ -245,7 +220,7 @@ hw_status hw_mmu_event_status(const void __iomem *base_address, u32 *irq_mask)
        return status;
 }
 
-hw_status hw_mmu_fault_addr_read(const void __iomem *base_address, u32 *addr)
+hw_status hw_mmu_fault_addr_read(void __iomem *base_address, u32 *addr)
 {
        hw_status status = 0;
 
@@ -255,7 +230,7 @@ hw_status hw_mmu_fault_addr_read(const void __iomem *base_address, u32 *addr)
        return status;
 }
 
-hw_status hw_mmu_ttb_set(const void __iomem *base_address, u32 ttb_phys_addr)
+hw_status hw_mmu_ttb_set(void __iomem *base_address, u32 ttb_phys_addr)
 {
        hw_status status = 0;
        u32 load_ttb;
@@ -267,7 +242,7 @@ hw_status hw_mmu_ttb_set(const void __iomem *base_address, u32 ttb_phys_addr)
        return status;
 }
 
-hw_status hw_mmu_twl_enable(const void __iomem *base_address)
+hw_status hw_mmu_twl_enable(void __iomem *base_address)
 {
        hw_status status = 0;
 
@@ -276,7 +251,7 @@ hw_status hw_mmu_twl_enable(const void __iomem *base_address)
        return status;
 }
 
-hw_status hw_mmu_twl_disable(const void __iomem *base_address)
+hw_status hw_mmu_twl_disable(void __iomem *base_address)
 {
        hw_status status = 0;
 
@@ -285,45 +260,7 @@ hw_status hw_mmu_twl_disable(const void __iomem *base_address)
        return status;
 }
 
-hw_status hw_mmu_tlb_flush(const void __iomem *base_address, u32 virtual_addr,
-                          u32 page_sz)
-{
-       hw_status status = 0;
-       u32 virtual_addr_tag;
-       enum hw_mmu_page_size_t pg_size_bits;
-
-       switch (page_sz) {
-       case HW_PAGE_SIZE4KB:
-               pg_size_bits = HW_MMU_SMALL_PAGE;
-               break;
-
-       case HW_PAGE_SIZE64KB:
-               pg_size_bits = HW_MMU_LARGE_PAGE;
-               break;
-
-       case HW_PAGE_SIZE1MB:
-               pg_size_bits = HW_MMU_SECTION;
-               break;
-
-       case HW_PAGE_SIZE16MB:
-               pg_size_bits = HW_MMU_SUPERSECTION;
-               break;
-
-       default:
-               return -EINVAL;
-       }
-
-       /* Generate the 20-bit tag from virtual address */
-       virtual_addr_tag = ((virtual_addr & MMU_ADDR_MASK) >> 12);
-
-       mmu_set_cam_entry(base_address, pg_size_bits, 0, 0, virtual_addr_tag);
-
-       mmu_flush_entry(base_address);
-
-       return status;
-}
-
-hw_status hw_mmu_tlb_add(const void __iomem *base_address,
+hw_status hw_mmu_tlb_add(void __iomem *base_address,
                         u32 physical_addr,
                         u32 virtual_addr,
                         u32 page_sz,
@@ -503,20 +440,8 @@ hw_status hw_mmu_pte_clear(const u32 pg_tbl_va, u32 virtual_addr, u32 page_size)
        return status;
 }
 
-/* mmu_flush_entry */
-static hw_status mmu_flush_entry(const void __iomem *base_address)
-{
-       hw_status status = 0;
-       u32 flush_entry_data = 0x1;
-
-       /* write values to register */
-       MMUMMU_FLUSH_ENTRY_WRITE_REGISTER32(base_address, flush_entry_data);
-
-       return status;
-}
-
 /* mmu_set_cam_entry */
-static hw_status mmu_set_cam_entry(const void __iomem *base_address,
+static hw_status mmu_set_cam_entry(void __iomem *base_address,
                                   const u32 page_sz,
                                   const u32 preserved_bit,
                                   const u32 valid_bit,
@@ -536,7 +461,7 @@ static hw_status mmu_set_cam_entry(const void __iomem *base_address,
 }
 
 /* mmu_set_ram_entry */
-static hw_status mmu_set_ram_entry(const void __iomem *base_address,
+static hw_status mmu_set_ram_entry(void __iomem *base_address,
                                   const u32 physical_addr,
                                   enum hw_endianism_t endianism,
                                   enum hw_element_size_t element_size,
@@ -556,7 +481,7 @@ static hw_status mmu_set_ram_entry(const void __iomem *base_address,
 
 }
 
-void hw_mmu_tlb_flush_all(const void __iomem *base)
+void hw_mmu_tlb_flush_all(void __iomem *base)
 {
        __raw_writel(1, base + MMU_GFLUSH);
 }
index 1458a2c..1c50bb3 100644 (file)
@@ -42,44 +42,41 @@ struct hw_mmu_map_attrs_t {
        bool donotlockmpupage;
 };
 
-extern hw_status hw_mmu_enable(const void __iomem *base_address);
+extern hw_status hw_mmu_enable(void __iomem *base_address);
 
-extern hw_status hw_mmu_disable(const void __iomem *base_address);
+extern hw_status hw_mmu_disable(void __iomem *base_address);
 
-extern hw_status hw_mmu_num_locked_set(const void __iomem *base_address,
+extern hw_status hw_mmu_num_locked_set(void __iomem *base_address,
                                       u32 num_locked_entries);
 
-extern hw_status hw_mmu_victim_num_set(const void __iomem *base_address,
+extern hw_status hw_mmu_victim_num_set(void __iomem *base_address,
                                       u32 victim_entry_num);
 
 /* For MMU faults */
-extern hw_status hw_mmu_event_ack(const void __iomem *base_address,
+extern hw_status hw_mmu_event_ack(void __iomem *base_address,
                                  u32 irq_mask);
 
-extern hw_status hw_mmu_event_disable(const void __iomem *base_address,
+extern hw_status hw_mmu_event_disable(void __iomem *base_address,
                                      u32 irq_mask);
 
-extern hw_status hw_mmu_event_enable(const void __iomem *base_address,
+extern hw_status hw_mmu_event_enable(void __iomem *base_address,
                                     u32 irq_mask);
 
-extern hw_status hw_mmu_event_status(const void __iomem *base_address,
+extern hw_status hw_mmu_event_status(void __iomem *base_address,
                                     u32 *irq_mask);
 
-extern hw_status hw_mmu_fault_addr_read(const void __iomem *base_address,
+extern hw_status hw_mmu_fault_addr_read(void __iomem *base_address,
                                        u32 *addr);
 
 /* Set the TT base address */
-extern hw_status hw_mmu_ttb_set(const void __iomem *base_address,
+extern hw_status hw_mmu_ttb_set(void __iomem *base_address,
                                u32 ttb_phys_addr);
 
-extern hw_status hw_mmu_twl_enable(const void __iomem *base_address);
+extern hw_status hw_mmu_twl_enable(void __iomem *base_address);
 
-extern hw_status hw_mmu_twl_disable(const void __iomem *base_address);
+extern hw_status hw_mmu_twl_disable(void __iomem *base_address);
 
-extern hw_status hw_mmu_tlb_flush(const void __iomem *base_address,
-                                 u32 virtual_addr, u32 page_sz);
-
-extern hw_status hw_mmu_tlb_add(const void __iomem *base_address,
+extern hw_status hw_mmu_tlb_add(void __iomem *base_address,
                                u32 physical_addr,
                                u32 virtual_addr,
                                u32 page_sz,
@@ -97,7 +94,7 @@ extern hw_status hw_mmu_pte_set(const u32 pg_tbl_va,
 extern hw_status hw_mmu_pte_clear(const u32 pg_tbl_va,
                                  u32 virtual_addr, u32 page_size);
 
-void hw_mmu_tlb_flush_all(const void __iomem *base);
+void hw_mmu_tlb_flush_all(void __iomem *base);
 
 static inline u32 hw_mmu_pte_addr_l1(u32 l1_base, u32 va)
 {
index 60a2781..b32c756 100644 (file)
@@ -53,8 +53,8 @@ struct cfg_hostres {
        u32 chnl_buf_size;
        u32 num_chnls;
        void __iomem *per_base;
-       u32 per_pm_base;
-       u32 core_pm_base;
+       void __iomem *per_pm_base;
+       void __iomem *core_pm_base;
        void __iomem *dmmu_base;
 };
 
index ed00d3d..5e2f4d8 100644 (file)
@@ -47,8 +47,8 @@
 #include <asm/cacheflush.h>
 #include <linux/dma-mapping.h>
 
-/* TODO -- Remove, once BP defines them */
-#define INT_DSP_MMU_IRQ        28
+/* TODO -- Remove, once omap-iommu is used */
+#define INT_DSP_MMU_IRQ        (28 + NR_IRQS)
 
 #define PRCM_VDD1 1
 
index 6795205..db1da28 100644 (file)
@@ -667,10 +667,10 @@ int drv_request_bridge_res_dsp(void **phost_resources)
                                                         OMAP_DSP_MEM3_SIZE);
                host_res->per_base = ioremap(OMAP_PER_CM_BASE,
                                                OMAP_PER_CM_SIZE);
-               host_res->per_pm_base = (u32) ioremap(OMAP_PER_PRM_BASE,
-                                                        OMAP_PER_PRM_SIZE);
-               host_res->core_pm_base = (u32) ioremap(OMAP_CORE_PRM_BASE,
-                                                         OMAP_CORE_PRM_SIZE);
+               host_res->per_pm_base = ioremap(OMAP_PER_PRM_BASE,
+                                               OMAP_PER_PRM_SIZE);
+               host_res->core_pm_base = ioremap(OMAP_CORE_PRM_BASE,
+                                                       OMAP_CORE_PRM_SIZE);
                host_res->dmmu_base = ioremap(OMAP_DMMU_BASE,
                                                 OMAP_DMMU_SIZE);
 
index c2fc613..294e9b4 100644 (file)
@@ -304,8 +304,7 @@ int node_allocate(struct proc_object *hprocessor,
        u32 pul_value;
        u32 dynext_base;
        u32 off_set = 0;
-       u32 ul_stack_seg_addr, ul_stack_seg_val;
-       u32 ul_gpp_mem_base;
+       u32 ul_stack_seg_val;
        struct cfg_hostres *host_res;
        struct bridge_dev_context *pbridge_context;
        u32 mapped_addr = 0;
@@ -581,6 +580,9 @@ func_cont:
                if (strcmp((char *)
                           pnode->dcd_props.obj_data.node_obj.ndb_props.
                           stack_seg_name, STACKSEGLABEL) == 0) {
+                       void __iomem *stack_seg;
+                       u32 stack_seg_pa;
+
                        status =
                            hnode_mgr->nldr_fxns.
                            get_fxn_addr(pnode->nldr_node_obj, "DYNEXT_BEG",
@@ -608,14 +610,21 @@ func_cont:
                                goto func_end;
                        }
 
-                       ul_gpp_mem_base = (u32) host_res->mem_base[1];
                        off_set = pul_value - dynext_base;
-                       ul_stack_seg_addr = ul_gpp_mem_base + off_set;
-                       ul_stack_seg_val = readl(ul_stack_seg_addr);
+                       stack_seg_pa = host_res->mem_phys[1] + off_set;
+                       stack_seg = ioremap(stack_seg_pa, SZ_32);
+                       if (!stack_seg) {
+                               status = -ENOMEM;
+                               goto func_end;
+                       }
+
+                       ul_stack_seg_val = readl(stack_seg);
+
+                       iounmap(stack_seg);
 
                        dev_dbg(bridge, "%s: StackSegVal = 0x%x, StackSegAddr ="
                                " 0x%x\n", __func__, ul_stack_seg_val,
-                               ul_stack_seg_addr);
+                               host_res->mem_base[1] + off_set);
 
                        pnode->create_args.asa.task_arg_obj.stack_seg =
                            ul_stack_seg_val;
index 653b074..6edefde 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 d6ce218..035c2c7 100644 (file)
@@ -3719,7 +3719,9 @@ restart:
                 */
                iscsit_thread_check_cpumask(conn, current, 1);
 
-               schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT);
+               wait_event_interruptible(conn->queues_wq,
+                                        !iscsit_conn_all_queues_empty(conn) ||
+                                        ts->status == ISCSI_THREAD_SET_RESET);
 
                if ((ts->status == ISCSI_THREAD_SET_RESET) ||
                     signal_pending(current))
index 2ba9f9b..21048db 100644 (file)
@@ -486,6 +486,7 @@ struct iscsi_tmr_req {
 };
 
 struct iscsi_conn {
+       wait_queue_head_t       queues_wq;
        /* Authentication Successful for this connection */
        u8                      auth_complete;
        /* State connection is currently in */
index cdc8a10..f8dbec0 100644 (file)
@@ -41,6 +41,7 @@
 
 static int iscsi_login_init_conn(struct iscsi_conn *conn)
 {
+       init_waitqueue_head(&conn->queues_wq);
        INIT_LIST_HEAD(&conn->conn_list);
        INIT_LIST_HEAD(&conn->conn_cmd_list);
        INIT_LIST_HEAD(&conn->immed_queue_list);
index afd98cc..1a91195 100644 (file)
@@ -488,7 +488,7 @@ void iscsit_add_cmd_to_immediate_queue(
        atomic_set(&conn->check_immediate_queue, 1);
        spin_unlock_bh(&conn->immed_queue_lock);
 
-       wake_up_process(conn->thread_set->tx_thread);
+       wake_up(&conn->queues_wq);
 }
 
 struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_conn *conn)
@@ -562,7 +562,7 @@ void iscsit_add_cmd_to_response_queue(
        atomic_inc(&cmd->response_queue_count);
        spin_unlock_bh(&conn->response_queue_lock);
 
-       wake_up_process(conn->thread_set->tx_thread);
+       wake_up(&conn->queues_wq);
 }
 
 struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *conn)
@@ -616,6 +616,24 @@ static void iscsit_remove_cmd_from_response_queue(
        }
 }
 
+bool iscsit_conn_all_queues_empty(struct iscsi_conn *conn)
+{
+       bool empty;
+
+       spin_lock_bh(&conn->immed_queue_lock);
+       empty = list_empty(&conn->immed_queue_list);
+       spin_unlock_bh(&conn->immed_queue_lock);
+
+       if (!empty)
+               return empty;
+
+       spin_lock_bh(&conn->response_queue_lock);
+       empty = list_empty(&conn->response_queue_list);
+       spin_unlock_bh(&conn->response_queue_lock);
+
+       return empty;
+}
+
 void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn)
 {
        struct iscsi_queue_req *qr, *qr_tmp;
index 44054bd..894d0f8 100644 (file)
@@ -25,6 +25,7 @@ extern struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_
 extern void iscsit_add_cmd_to_response_queue(struct iscsi_cmd *, struct iscsi_conn *, u8);
 extern struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *);
 extern void iscsit_remove_cmd_from_tx_queues(struct iscsi_cmd *, struct iscsi_conn *);
+extern bool iscsit_conn_all_queues_empty(struct iscsi_conn *);
 extern void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *);
 extern void iscsit_release_cmd(struct iscsi_cmd *);
 extern void iscsit_free_cmd(struct iscsi_cmd *);
index 015f5be..c123327 100644 (file)
@@ -3206,7 +3206,8 @@ static int __init target_core_init_configfs(void)
        if (ret < 0)
                goto out;
 
-       if (core_dev_setup_virtual_lun0() < 0)
+       ret = core_dev_setup_virtual_lun0();
+       if (ret < 0)
                goto out;
 
        return 0;
index 8d774da..9abef9f 100644 (file)
@@ -850,20 +850,20 @@ int se_dev_check_shutdown(struct se_device *dev)
 
 static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size)
 {
-       u32 tmp, aligned_max_sectors;
+       u32 aligned_max_sectors;
+       u32 alignment;
        /*
         * Limit max_sectors to a PAGE_SIZE aligned value for modern
         * transport_allocate_data_tasks() operation.
         */
-       tmp = rounddown((max_sectors * block_size), PAGE_SIZE);
-       aligned_max_sectors = (tmp / block_size);
-       if (max_sectors != aligned_max_sectors) {
-               printk(KERN_INFO "Rounding down aligned max_sectors from %u"
-                               " to %u\n", max_sectors, aligned_max_sectors);
-               return aligned_max_sectors;
-       }
+       alignment = max(1ul, PAGE_SIZE / block_size);
+       aligned_max_sectors = rounddown(max_sectors, alignment);
+
+       if (max_sectors != aligned_max_sectors)
+               pr_info("Rounding down aligned max_sectors from %u to %u\n",
+                       max_sectors, aligned_max_sectors);
 
-       return max_sectors;
+       return aligned_max_sectors;
 }
 
 void se_dev_set_default_attribs(
index 868f8aa..a6e27d9 100644 (file)
@@ -135,6 +135,12 @@ static int sbc_emulate_verify(struct se_cmd *cmd)
        return 0;
 }
 
+static int sbc_emulate_noop(struct se_cmd *cmd)
+{
+       target_complete_cmd(cmd, GOOD);
+       return 0;
+}
+
 static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors)
 {
        return cmd->se_dev->se_sub_dev->se_dev_attrib.block_size * sectors;
@@ -531,6 +537,18 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)
                size = 0;
                cmd->execute_cmd = sbc_emulate_verify;
                break;
+       case REZERO_UNIT:
+       case SEEK_6:
+       case SEEK_10:
+               /*
+                * There are still clients out there which use these old SCSI-2
+                * commands. This mainly happens when running VMs with legacy
+                * guest systems, connected via SCSI command pass-through to
+                * iSCSI targets. Make them happy and return status GOOD.
+                */
+               size = 0;
+               cmd->execute_cmd = sbc_emulate_noop;
+               break;
        default:
                ret = spc_parse_cdb(cmd, &size);
                if (ret)
index 9229bd9..6fd434d 100644 (file)
@@ -605,6 +605,8 @@ static int spc_emulate_inquiry(struct se_cmd *cmd)
        unsigned char buf[SE_INQUIRY_BUF];
        int p, ret;
 
+       memset(buf, 0, SE_INQUIRY_BUF);
+
        if (dev == tpg->tpg_virt_lun0.lun_se_dev)
                buf[0] = 0x3f; /* Not connected */
        else
index 1c59a3c..be75c43 100644 (file)
@@ -140,15 +140,15 @@ void core_tmr_abort_task(
                printk("ABORT_TASK: Found referenced %s task_tag: %u\n",
                        se_cmd->se_tfo->get_fabric_name(), ref_tag);
 
-               spin_lock_irq(&se_cmd->t_state_lock);
+               spin_lock(&se_cmd->t_state_lock);
                if (se_cmd->transport_state & CMD_T_COMPLETE) {
                        printk("ABORT_TASK: ref_tag: %u already complete, skipping\n", ref_tag);
-                       spin_unlock_irq(&se_cmd->t_state_lock);
+                       spin_unlock(&se_cmd->t_state_lock);
                        spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
                        goto out;
                }
                se_cmd->transport_state |= CMD_T_ABORTED;
-               spin_unlock_irq(&se_cmd->t_state_lock);
+               spin_unlock(&se_cmd->t_state_lock);
 
                list_del_init(&se_cmd->se_cmd_list);
                kref_get(&se_cmd->cmd_kref);
index c33baff..dcecbfb 100644 (file)
@@ -1616,7 +1616,6 @@ static void target_complete_tmr_failure(struct work_struct *work)
 
        se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST;
        se_cmd->se_tfo->queue_tm_rsp(se_cmd);
-       transport_generic_free_cmd(se_cmd, 0);
 }
 
 /**
@@ -1820,8 +1819,10 @@ void target_execute_cmd(struct se_cmd *cmd)
        /*
         * If the received CDB has aleady been aborted stop processing it here.
         */
-       if (transport_check_aborted_status(cmd, 1))
+       if (transport_check_aborted_status(cmd, 1)) {
+               complete(&cmd->t_transport_stop_comp);
                return;
+       }
 
        /*
         * Determine if IOCTL context caller in requesting the stopping of this
@@ -3068,7 +3069,7 @@ void transport_send_task_abort(struct se_cmd *cmd)
        unsigned long flags;
 
        spin_lock_irqsave(&cmd->t_state_lock, flags);
-       if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) {
+       if (cmd->se_cmd_flags & (SCF_SENT_CHECK_CONDITION | SCF_SENT_DELAYED_TAS)) {
                spin_unlock_irqrestore(&cmd->t_state_lock, flags);
                return;
        }
index edfd67d..e1cb6bd 100644 (file)
@@ -22,6 +22,7 @@ config THERMAL_HWMON
 config CPU_THERMAL
        bool "generic cpu cooling support"
        depends on THERMAL && CPU_FREQ
+       select CPU_FREQ_TABLE
        help
          This implements the generic cpu cooling mechanism through frequency
          reduction, cpu hotplug and any other ways of reducing temperature. An
@@ -50,6 +51,7 @@ config RCAR_THERMAL
 config EXYNOS_THERMAL
        tristate "Temperature sensor on Samsung EXYNOS"
        depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5) && THERMAL
+       select CPU_FREQ_TABLE
        help
          If you say yes here you get support for TMU (Thermal Managment
          Unit) on SAMSUNG EXYNOS series of SoC.
index fd03e85..6dd29e4 100644 (file)
@@ -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)
index d445271..f7a1b57 100644 (file)
@@ -210,7 +210,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
                goto error_free_priv;
        }
 
-       zone = thermal_zone_device_register("rcar_thermal", 0, priv,
+       zone = thermal_zone_device_register("rcar_thermal", 0, 0, priv,
                                            &rcar_thermal_zone_ops, 0, 0);
        if (IS_ERR(zone)) {
                dev_err(&pdev->dev, "thermal zone device is NULL\n");
index a5dec1c..13ee53b 100644 (file)
@@ -424,7 +424,6 @@ static void hvc_hangup(struct tty_struct *tty)
 {
        struct hvc_struct *hp = tty->driver_data;
        unsigned long flags;
-       int temp_open_count;
 
        if (!hp)
                return;
@@ -444,7 +443,6 @@ static void hvc_hangup(struct tty_struct *tty)
                return;
        }
 
-       temp_open_count = hp->port.count;
        hp->port.count = 0;
        spin_unlock_irqrestore(&hp->port.lock, flags);
        tty_port_tty_set(&hp->port, NULL);
@@ -453,11 +451,6 @@ static void hvc_hangup(struct tty_struct *tty)
 
        if (hp->ops->notifier_hangup)
                hp->ops->notifier_hangup(hp, hp->data);
-
-       while(temp_open_count) {
-               --temp_open_count;
-               tty_port_put(&hp->port);
-       }
 }
 
 /*
index 8f1dd2c..f3d0edf 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 233fbaa..2a53be5 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 3d7e1ee..65f891b 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 2bc28a5..1ab1d2c 100644 (file)
@@ -1239,6 +1239,7 @@ static int __devexit max310x_remove(struct spi_device *spi)
 static const struct spi_device_id max310x_id_table[] = {
        { "max3107",    MAX310X_TYPE_MAX3107 },
        { "max3108",    MAX310X_TYPE_MAX3108 },
+       { }
 };
 MODULE_DEVICE_TABLE(spi, max310x_id_table);
 
index 6ede6fd..6d3d26a 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 b7086d0..e821068 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 9be296c..6ee5900 100644 (file)
@@ -530,7 +530,8 @@ static inline int sci_rxd_in(struct uart_port *port)
        if (s->cfg->port_reg <= 0)
                return 1;
 
-       return !!__raw_readb(s->cfg->port_reg);
+       /* Cast for ARM damage */
+       return !!__raw_readb((void __iomem *)s->cfg->port_reg);
 }
 
 /* ********************************************************************** *
index 0572889..16ee6ce 100644 (file)
@@ -452,6 +452,7 @@ static struct sysrq_key_op *sysrq_key_table[36] = {
        NULL,                           /* v */
        &sysrq_showstate_blocked_op,    /* w */
        /* x: May be registered on ppc/powerpc for xmon */
+       /* x: May be registered on sparc64 for global PMU dump */
        NULL,                           /* x */
        /* y: May be registered on sparc64 for global register dump */
        NULL,                           /* y */
index f87d7e8..4e0d0c3 100644 (file)
@@ -539,25 +539,25 @@ static void insert_char(struct vc_data *vc, unsigned int nr)
 {
        unsigned short *p = (unsigned short *) vc->vc_pos;
 
-       scr_memmovew(p + nr, p, vc->vc_cols - vc->vc_x);
+       scr_memmovew(p + nr, p, (vc->vc_cols - vc->vc_x) * 2);
        scr_memsetw(p, vc->vc_video_erase_char, nr * 2);
        vc->vc_need_wrap = 0;
        if (DO_UPDATE(vc))
                do_update_region(vc, (unsigned long) p,
-                       (vc->vc_cols - vc->vc_x) / 2 + 1);
+                       vc->vc_cols - vc->vc_x);
 }
 
 static void delete_char(struct vc_data *vc, unsigned int nr)
 {
        unsigned short *p = (unsigned short *) vc->vc_pos;
 
-       scr_memcpyw(p, p + nr, vc->vc_cols - vc->vc_x - nr);
+       scr_memcpyw(p, p + nr, (vc->vc_cols - vc->vc_x - nr) * 2);
        scr_memsetw(p + vc->vc_cols - vc->vc_x - nr, vc->vc_video_erase_char,
                        nr * 2);
        vc->vc_need_wrap = 0;
        if (DO_UPDATE(vc))
                do_update_region(vc, (unsigned long) p,
-                       (vc->vc_cols - vc->vc_x) / 2);
+                       vc->vc_cols - vc->vc_x);
 }
 
 static int softcursor_original;
index 981f213..6e49ec6 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 e0356cb..b78fbe2 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 ddd820d..6056db7 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 1e741bc..f034716 100644 (file)
@@ -2151,8 +2151,15 @@ EXPORT_SYMBOL_GPL(usb_bus_start_enum);
 irqreturn_t usb_hcd_irq (int irq, void *__hcd)
 {
        struct usb_hcd          *hcd = __hcd;
+       unsigned long           flags;
        irqreturn_t             rc;
 
+       /* IRQF_DISABLED doesn't work correctly with shared IRQs
+        * when the first handler doesn't use it.  So let's just
+        * assume it's never used.
+        */
+       local_irq_save(flags);
+
        if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd)))
                rc = IRQ_NONE;
        else if (hcd->driver->irq(hcd) == IRQ_NONE)
@@ -2160,6 +2167,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
        else
                rc = IRQ_HANDLED;
 
+       local_irq_restore(flags);
        return rc;
 }
 EXPORT_SYMBOL_GPL(usb_hcd_irq);
@@ -2347,6 +2355,14 @@ static int usb_hcd_request_irqs(struct usb_hcd *hcd,
        int retval;
 
        if (hcd->driver->irq) {
+
+               /* IRQF_DISABLED doesn't work as advertised when used together
+                * with IRQF_SHARED. As usb_hcd_irq() will always disable
+                * interrupts we can remove it here.
+                */
+               if (irqflags & IRQF_SHARED)
+                       irqflags &= ~IRQF_DISABLED;
+
                snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
                                hcd->driver->description, hcd->self.busnum);
                retval = request_irq(irqnum, &usb_hcd_irq, irqflags,
index 673ee46..1af04bd 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 */
@@ -3241,8 +3244,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;
        }
@@ -3320,16 +3322,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 +3406,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 b415c0c..c14ebc9 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 c9e729a..7b7dedd 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 e426ad6..4bfa78a 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/usb/ehci_def.h>
 #include <linux/delay.h>
 #include <linux/serial_core.h>
+#include <linux/kconfig.h>
 #include <linux/kgdb.h>
 #include <linux/kthread.h>
 #include <asm/io.h>
@@ -614,12 +615,6 @@ err:
        return -ENODEV;
 }
 
-int dbgp_external_startup(struct usb_hcd *hcd)
-{
-       return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup();
-}
-EXPORT_SYMBOL_GPL(dbgp_external_startup);
-
 static int ehci_reset_port(int port)
 {
        u32 portsc;
@@ -979,6 +974,7 @@ struct console early_dbgp_console = {
        .index =        -1,
 };
 
+#if IS_ENABLED(CONFIG_USB_EHCI_HCD)
 int dbgp_reset_prep(struct usb_hcd *hcd)
 {
        int ret = xen_dbgp_reset_prep(hcd);
@@ -1007,6 +1003,13 @@ int dbgp_reset_prep(struct usb_hcd *hcd)
 }
 EXPORT_SYMBOL_GPL(dbgp_reset_prep);
 
+int dbgp_external_startup(struct usb_hcd *hcd)
+{
+       return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup();
+}
+EXPORT_SYMBOL_GPL(dbgp_external_startup);
+#endif /* USB_EHCI_HCD */
+
 #ifdef CONFIG_KGDB
 
 static char kgdbdbgp_buf[DBGP_MAX_PACKET];
index dfb51a4..e0ff51b 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 f696fb9..21a9861 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 43ac748..c009263 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 6458764..4ec3c0d 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/ctype.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
+#include <linux/if_vlan.h>
 
 #include "u_ether.h"
 
@@ -295,7 +296,7 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)
                while (skb2) {
                        if (status < 0
                                        || ETH_HLEN > skb2->len
-                                       || skb2->len > ETH_FRAME_LEN) {
+                                       || skb2->len > VLAN_ETH_FRAME_LEN) {
                                dev->net->stats.rx_errors++;
                                dev->net->stats.rx_length_errors++;
                                DBG(dev, "rx length %d\n", skb2->len);
index 9bfde82..0d2f35c 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 ca75965..aa0f328 100644 (file)
@@ -113,7 +113,7 @@ static int ehci_hcd_ls1x_probe(struct platform_device *pdev)
                goto err_put_hcd;
        }
 
-       ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+       ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
        if (ret)
                goto err_put_hcd;
 
index 8e7eca6..9c2717d 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 96722bf..d3c9a3e 100644 (file)
@@ -85,6 +85,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 +97,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 84201cd..41e378f 100644 (file)
@@ -56,7 +56,7 @@ static int ohci_xls_probe_internal(const struct hc_driver *driver,
                goto err3;
        }
 
-       retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
+       retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
        if (retval != 0)
                goto err4;
        return retval;
index 966d148..39f9e4a 100644 (file)
@@ -545,7 +545,14 @@ static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = {
                /*  Pegatron Lucid (Ordissimo AIRIS) */
                .matches = {
                        DMI_MATCH(DMI_BOARD_NAME, "M11JB"),
-                       DMI_MATCH(DMI_BIOS_VERSION, "Lucid-GE-133"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"),
+               },
+       },
+       {
+               /*  Pegatron Lucid (Ordissimo) */
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_NAME, "Ordissimo"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"),
                },
        },
        { }
index e478049..68ebf20 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 4b436f5..5f3a7c7 100644 (file)
@@ -544,7 +544,6 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci,
        int i;
        /* Fields are 32 bits wide, DMA addresses are in bytes */
        int field_size = 32 / 8;
-       struct xhci_slot_ctx *slot_ctx;
        dma_addr_t dma = ctx->dma;
        int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params);
 
@@ -570,7 +569,6 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci,
                        dbg_rsvd64(xhci, (u64 *)ctrl_ctx, dma);
        }
 
-       slot_ctx = xhci_get_slot_ctx(xhci, ctx);
        xhci_dbg_slot_ctx(xhci, ctx);
        xhci_dbg_ep_ctx(xhci, ctx, last_ep);
 }
index aa90ad4..a686cf4 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 c6ebb17..4e1a894 100644 (file)
@@ -1228,6 +1228,17 @@ static void xhci_cmd_to_noop(struct xhci_hcd *xhci, struct xhci_cd *cur_cd)
        cur_seg = find_trb_seg(xhci->cmd_ring->first_seg,
                        xhci->cmd_ring->dequeue, &cycle_state);
 
+       if (!cur_seg) {
+               xhci_warn(xhci, "Command ring mismatch, dequeue = %p %llx (dma)\n",
+                               xhci->cmd_ring->dequeue,
+                               (unsigned long long)
+                               xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
+                                       xhci->cmd_ring->dequeue));
+               xhci_debug_ring(xhci, xhci->cmd_ring);
+               xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring);
+               return;
+       }
+
        /* find the command trb matched by cd from command ring */
        for (cmd_trb = xhci->cmd_ring->dequeue;
                        cmd_trb != xhci->cmd_ring->enqueue;
index 8d7fcbb..c9e419f 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;
@@ -1626,7 +1627,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
        struct xhci_hcd *xhci;
        struct xhci_container_ctx *in_ctx, *out_ctx;
        unsigned int ep_index;
-       struct xhci_ep_ctx *ep_ctx;
        struct xhci_slot_ctx *slot_ctx;
        struct xhci_input_control_ctx *ctrl_ctx;
        u32 added_ctxs;
@@ -1662,7 +1662,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
        out_ctx = virt_dev->out_ctx;
        ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
        ep_index = xhci_get_endpoint_index(&ep->desc);
-       ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
 
        /* If this endpoint is already in use, and the upper layers are trying
         * to add it again without dropping it, reject the addition.
@@ -1816,6 +1815,8 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci,
        case COMP_EBADSLT:
                dev_warn(&udev->dev, "WARN: slot not enabled for"
                                "evaluate context command.\n");
+               ret = -EINVAL;
+               break;
        case COMP_CTX_STATE:
                dev_warn(&udev->dev, "WARN: invalid context state for "
                                "evaluate context command.\n");
@@ -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 4223d76..6589268 100644 (file)
@@ -158,3 +158,4 @@ int ezusb_fx2_ihex_firmware_download(struct usb_device *dev,
 }
 EXPORT_SYMBOL_GPL(ezusb_fx2_ihex_firmware_download);
 
+MODULE_LICENSE("GPL");
index 457f25e..c964d6a 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 444346e..ff5f112 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 d0b87e7..b6b84da 100644 (file)
@@ -707,11 +707,12 @@ static void rxstate(struct musb *musb, struct musb_request *req)
                fifo_count = musb_readw(epio, MUSB_RXCOUNT);
 
                /*
-                *  use mode 1 only if we expect data of at least ep packet_sz
-                *  and have not yet received a short packet
+                * Enable Mode 1 on RX transfers only when short_not_ok flag
+                * is set. Currently short_not_ok flag is set only from
+                * file_storage and f_mass_storage drivers
                 */
-               if ((request->length - request->actual >= musb_ep->packet_sz) &&
-                       (fifo_count >= musb_ep->packet_sz))
+
+               if (request->short_not_ok && fifo_count == musb_ep->packet_sz)
                        use_mode_1 = 1;
                else
                        use_mode_1 = 0;
@@ -727,6 +728,27 @@ static void rxstate(struct musb *musb, struct musb_request *req)
                                c = musb->dma_controller;
                                channel = musb_ep->dma;
 
+       /* We use DMA Req mode 0 in rx_csr, and DMA controller operates in
+        * mode 0 only. So we do not get endpoint interrupts due to DMA
+        * completion. We only get interrupts from DMA controller.
+        *
+        * We could operate in DMA mode 1 if we knew the size of the tranfer
+        * in advance. For mass storage class, request->length = what the host
+        * sends, so that'd work.  But for pretty much everything else,
+        * request->length is routinely more than what the host sends. For
+        * most these gadgets, end of is signified either by a short packet,
+        * or filling the last byte of the buffer.  (Sending extra data in
+        * that last pckate should trigger an overflow fault.)  But in mode 1,
+        * we don't get DMA completion interrupt for short packets.
+        *
+        * Theoretically, we could enable DMAReq irq (MUSB_RXCSR_DMAMODE = 1),
+        * to get endpoint interrupt on every DMA req, but that didn't seem
+        * to work reliably.
+        *
+        * REVISIT an updated g_file_storage can set req->short_not_ok, which
+        * then becomes usable as a runtime "use mode 1" hint...
+        */
+
                                /* Experimental: Mode1 works with mass storage use cases */
                                if (use_mode_1) {
                                        csr |= MUSB_RXCSR_AUTOCLEAR;
index d62a91f..0e62f50 100644 (file)
@@ -65,7 +65,7 @@ static int __devinit ux500_probe(struct platform_device *pdev)
        struct platform_device          *musb;
        struct ux500_glue               *glue;
        struct clk                      *clk;
-
+       int                             musbid;
        int                             ret = -ENOMEM;
 
        glue = kzalloc(sizeof(*glue), GFP_KERNEL);
index d8c8a42..6223062 100644 (file)
@@ -58,7 +58,7 @@ config USB_ULPI_VIEWPORT
 
 config TWL4030_USB
        tristate "TWL4030 USB Transceiver Driver"
-       depends on TWL4030_CORE && REGULATOR_TWL4030
+       depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
        select USB_OTG_UTILS
        help
          Enable this to support the USB OTG transceiver on TWL4030
@@ -68,7 +68,7 @@ config TWL4030_USB
 
 config TWL6030_USB
        tristate "TWL6030 USB Transceiver Driver"
-       depends on TWL4030_CORE && OMAP_USB2
+       depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS
        select USB_OTG_UTILS
        help
          Enable this to support the USB OTG transceiver on TWL6030
index 143c4e9..c021b20 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 35c5208..61933a9 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 9b69a13..069cd76 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 08786c0..3d80c7b 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 cf2522c..bd50a8a 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 9944942..ea29556 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 e9c7046..d255f66 100644 (file)
@@ -242,13 +242,11 @@ out:      kfree(buffer);
        return r;
 }
 
-/* allocate private data */
-static int ch341_attach(struct usb_serial *serial)
+static int ch341_port_probe(struct usb_serial_port *port)
 {
        struct ch341_private *priv;
        int r;
 
-       /* private data */
        priv = kzalloc(sizeof(struct ch341_private), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
@@ -258,17 +256,27 @@ static int ch341_attach(struct usb_serial *serial)
        priv->baud_rate = DEFAULT_BAUD_RATE;
        priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
 
-       r = ch341_configure(serial->dev, priv);
+       r = ch341_configure(port->serial->dev, priv);
        if (r < 0)
                goto error;
 
-       usb_set_serial_port_data(serial->port[0], priv);
+       usb_set_serial_port_data(port, priv);
        return 0;
 
 error: kfree(priv);
        return r;
 }
 
+static int ch341_port_remove(struct usb_serial_port *port)
+{
+       struct ch341_private *priv;
+
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
+}
+
 static int ch341_carrier_raised(struct usb_serial_port *port)
 {
        struct ch341_private *priv = usb_get_serial_port_data(port);
@@ -304,7 +312,7 @@ static void ch341_close(struct usb_serial_port *port)
 static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
-       struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]);
+       struct ch341_private *priv = usb_get_serial_port_data(port);
        int r;
 
        priv->baud_rate = DEFAULT_BAUD_RATE;
@@ -608,7 +616,8 @@ static struct usb_serial_driver ch341_device = {
        .tiocmget          = ch341_tiocmget,
        .tiocmset          = ch341_tiocmset,
        .read_int_callback = ch341_read_int_callback,
-       .attach            = ch341_attach,
+       .port_probe        = ch341_port_probe,
+       .port_remove       = ch341_port_remove,
        .reset_resume      = ch341_reset_resume,
 };
 
index 28af5ac..eb033fc 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 2a7aecc..4ee77dc 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 1befce2..f0da127 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 c86f68c..b50fa1c 100644 (file)
@@ -244,6 +244,8 @@ static int digi_startup_device(struct usb_serial *serial);
 static int digi_startup(struct usb_serial *serial);
 static void digi_disconnect(struct usb_serial *serial);
 static void digi_release(struct usb_serial *serial);
+static int digi_port_probe(struct usb_serial_port *port);
+static int digi_port_remove(struct usb_serial_port *port);
 static void digi_read_bulk_callback(struct urb *urb);
 static int digi_read_inb_callback(struct urb *urb);
 static int digi_read_oob_callback(struct urb *urb);
@@ -294,6 +296,8 @@ static struct usb_serial_driver digi_acceleport_2_device = {
        .attach =                       digi_startup,
        .disconnect =                   digi_disconnect,
        .release =                      digi_release,
+       .port_probe =                   digi_port_probe,
+       .port_remove =                  digi_port_remove,
 };
 
 static struct usb_serial_driver digi_acceleport_4_device = {
@@ -320,6 +324,8 @@ static struct usb_serial_driver digi_acceleport_4_device = {
        .attach =                       digi_startup,
        .disconnect =                   digi_disconnect,
        .release =                      digi_release,
+       .port_probe =                   digi_port_probe,
+       .port_remove =                  digi_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
@@ -1240,59 +1246,50 @@ static int digi_startup_device(struct usb_serial *serial)
        return ret;
 }
 
-
-static int digi_startup(struct usb_serial *serial)
+static int digi_port_init(struct usb_serial_port *port, unsigned port_num)
 {
-
-       int i;
        struct digi_port *priv;
-       struct digi_serial *serial_priv;
 
-       /* allocate the private data structures for all ports */
-       /* number of regular ports + 1 for the out-of-band port */
-       for (i = 0; i < serial->type->num_ports + 1; i++) {
-               /* allocate port private structure */
-               priv = kmalloc(sizeof(struct digi_port), GFP_KERNEL);
-               if (priv == NULL) {
-                       while (--i >= 0)
-                               kfree(usb_get_serial_port_data(serial->port[i]));
-                       return 1;                       /* error */
-               }
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
 
-               /* initialize port private structure */
-               spin_lock_init(&priv->dp_port_lock);
-               priv->dp_port_num = i;
-               priv->dp_out_buf_len = 0;
-               priv->dp_write_urb_in_use = 0;
-               priv->dp_modem_signals = 0;
-               init_waitqueue_head(&priv->dp_modem_change_wait);
-               priv->dp_transmit_idle = 0;
-               init_waitqueue_head(&priv->dp_transmit_idle_wait);
-               priv->dp_throttled = 0;
-               priv->dp_throttle_restart = 0;
-               init_waitqueue_head(&priv->dp_flush_wait);
-               init_waitqueue_head(&priv->dp_close_wait);
-               INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock);
-               priv->dp_port = serial->port[i];
-               /* initialize write wait queue for this port */
-               init_waitqueue_head(&serial->port[i]->write_wait);
-
-               usb_set_serial_port_data(serial->port[i], priv);
-       }
+       spin_lock_init(&priv->dp_port_lock);
+       priv->dp_port_num = port_num;
+       init_waitqueue_head(&priv->dp_modem_change_wait);
+       init_waitqueue_head(&priv->dp_transmit_idle_wait);
+       init_waitqueue_head(&priv->dp_flush_wait);
+       init_waitqueue_head(&priv->dp_close_wait);
+       INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock);
+       priv->dp_port = port;
 
-       /* allocate serial private structure */
-       serial_priv = kmalloc(sizeof(struct digi_serial), GFP_KERNEL);
-       if (serial_priv == NULL) {
-               for (i = 0; i < serial->type->num_ports + 1; i++)
-                       kfree(usb_get_serial_port_data(serial->port[i]));
-               return 1;                       /* error */
-       }
+       init_waitqueue_head(&port->write_wait);
+
+       usb_set_serial_port_data(port, priv);
+
+       return 0;
+}
+
+static int digi_startup(struct usb_serial *serial)
+{
+       struct digi_serial *serial_priv;
+       int ret;
+
+       serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL);
+       if (!serial_priv)
+               return -ENOMEM;
 
-       /* initialize serial private structure */
        spin_lock_init(&serial_priv->ds_serial_lock);
        serial_priv->ds_oob_port_num = serial->type->num_ports;
        serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num];
-       serial_priv->ds_device_started = 0;
+
+       ret = digi_port_init(serial_priv->ds_oob_port,
+                                               serial_priv->ds_oob_port_num);
+       if (ret) {
+               kfree(serial_priv);
+               return ret;
+       }
+
        usb_set_serial_data(serial, serial_priv);
 
        return 0;
@@ -1313,15 +1310,35 @@ static void digi_disconnect(struct usb_serial *serial)
 
 static void digi_release(struct usb_serial *serial)
 {
-       int i;
+       struct digi_serial *serial_priv;
+       struct digi_port *priv;
+
+       serial_priv = usb_get_serial_data(serial);
+
+       priv = usb_get_serial_port_data(serial_priv->ds_oob_port);
+       kfree(priv);
 
-       /* free the private data structures for all ports */
-       /* number of regular ports + 1 for the out-of-band port */
-       for (i = 0; i < serial->type->num_ports + 1; i++)
-               kfree(usb_get_serial_port_data(serial->port[i]));
-       kfree(usb_get_serial_data(serial));
+       kfree(serial_priv);
 }
 
+static int digi_port_probe(struct usb_serial_port *port)
+{
+       unsigned port_num;
+
+       port_num = port->number - port->serial->minor;
+
+       return digi_port_init(port, port_num);
+}
+
+static int digi_port_remove(struct usb_serial_port *port)
+{
+       struct digi_port *priv;
+
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
+}
 
 static void digi_read_bulk_callback(struct urb *urb)
 {
index 2444771..6e4eb57 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 3ee9264..203358d 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 8e6faaf..5acc0d1 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 350afdd..1511dd0 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 a2209cd..60023c2 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 20a132e..4264821 100644 (file)
@@ -203,8 +203,7 @@ static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port)
        return 0;
 }
 
-/* fake probe - only to allocate data structures */
-static int ipw_probe(struct usb_serial *serial, const struct usb_device_id *id)
+static int ipw_attach(struct usb_serial *serial)
 {
        struct usb_wwan_intf_private *data;
 
@@ -303,9 +302,9 @@ static struct usb_serial_driver ipw_device = {
        .num_ports =            1,
        .open =                 ipw_open,
        .close =                ipw_close,
-       .probe =                ipw_probe,
-       .attach =               usb_wwan_startup,
+       .attach =               ipw_attach,
        .release =              ipw_release,
+       .port_probe =           usb_wwan_port_probe,
        .port_remove =          usb_wwan_port_remove,
        .dtr_rts =              ipw_dtr_rts,
        .write =                usb_wwan_write,
index 01da3ea..cd5533e 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 29c943d..cff8dd5 100644 (file)
@@ -1374,13 +1374,9 @@ static struct callbacks {
           data in device_details */
 static void keyspan_setup_urbs(struct usb_serial *serial)
 {
-       int                             i, j;
        struct keyspan_serial_private   *s_priv;
        const struct keyspan_device_details     *d_details;
-       struct usb_serial_port          *port;
-       struct keyspan_port_private     *p_priv;
        struct callbacks                *cback;
-       int                             endp;
 
        s_priv = usb_get_serial_data(serial);
        d_details = s_priv->device_details;
@@ -1404,45 +1400,6 @@ static void keyspan_setup_urbs(struct usb_serial *serial)
                (serial, d_details->glocont_endpoint, USB_DIR_OUT,
                 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
                 cback->glocont_callback);
-
-       /* Setup endpoints for each port specific thing */
-       for (i = 0; i < d_details->num_ports; i++) {
-               port = serial->port[i];
-               p_priv = usb_get_serial_port_data(port);
-
-               /* Do indat endpoints first, once for each flip */
-               endp = d_details->indat_endpoints[i];
-               for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) {
-                       p_priv->in_urbs[j] = keyspan_setup_urb
-                               (serial, endp, USB_DIR_IN, port,
-                                p_priv->in_buffer[j], 64,
-                                cback->indat_callback);
-               }
-               for (; j < 2; ++j)
-                       p_priv->in_urbs[j] = NULL;
-
-               /* outdat endpoints also have flip */
-               endp = d_details->outdat_endpoints[i];
-               for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) {
-                       p_priv->out_urbs[j] = keyspan_setup_urb
-                               (serial, endp, USB_DIR_OUT, port,
-                                p_priv->out_buffer[j], 64,
-                                cback->outdat_callback);
-               }
-               for (; j < 2; ++j)
-                       p_priv->out_urbs[j] = NULL;
-
-               /* inack endpoint */
-               p_priv->inack_urb = keyspan_setup_urb
-                       (serial, d_details->inack_endpoints[i], USB_DIR_IN,
-                        port, p_priv->inack_buffer, 1, cback->inack_callback);
-
-               /* outcont endpoint */
-               p_priv->outcont_urb = keyspan_setup_urb
-                       (serial, d_details->outcont_endpoints[i], USB_DIR_OUT,
-                        port, p_priv->outcont_buffer, 64,
-                        cback->outcont_callback);
-       }
 }
 
 /* usa19 function doesn't require prescaler */
@@ -2407,9 +2364,7 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
 static int keyspan_startup(struct usb_serial *serial)
 {
        int                             i, err;
-       struct usb_serial_port          *port;
        struct keyspan_serial_private   *s_priv;
-       struct keyspan_port_private     *p_priv;
        const struct keyspan_device_details     *d_details;
 
        for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
@@ -2432,19 +2387,6 @@ static int keyspan_startup(struct usb_serial *serial)
        s_priv->device_details = d_details;
        usb_set_serial_data(serial, s_priv);
 
-       /* Now setup per port private data */
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-               p_priv = kzalloc(sizeof(struct keyspan_port_private),
-                                                               GFP_KERNEL);
-               if (!p_priv) {
-                       dev_dbg(&port->dev, "%s - kmalloc for keyspan_port_private (%d) failed!.\n", __func__, i);
-                       return 1;
-               }
-               p_priv->device_details = d_details;
-               usb_set_serial_port_data(port, p_priv);
-       }
-
        keyspan_setup_urbs(serial);
 
        if (s_priv->instat_urb != NULL) {
@@ -2463,59 +2405,111 @@ static int keyspan_startup(struct usb_serial *serial)
 
 static void keyspan_disconnect(struct usb_serial *serial)
 {
-       int                             i, j;
-       struct usb_serial_port          *port;
-       struct keyspan_serial_private   *s_priv;
-       struct keyspan_port_private     *p_priv;
+       struct keyspan_serial_private *s_priv;
 
        s_priv = usb_get_serial_data(serial);
 
-       /* Stop reading/writing urbs */
        stop_urb(s_priv->instat_urb);
        stop_urb(s_priv->glocont_urb);
        stop_urb(s_priv->indat_urb);
-       for (i = 0; i < serial->num_ports; ++i) {
-               port = serial->port[i];
-               p_priv = usb_get_serial_port_data(port);
-               stop_urb(p_priv->inack_urb);
-               stop_urb(p_priv->outcont_urb);
-               for (j = 0; j < 2; j++) {
-                       stop_urb(p_priv->in_urbs[j]);
-                       stop_urb(p_priv->out_urbs[j]);
-               }
-       }
+}
+
+static void keyspan_release(struct usb_serial *serial)
+{
+       struct keyspan_serial_private *s_priv;
+
+       s_priv = usb_get_serial_data(serial);
 
-       /* Now free them */
        usb_free_urb(s_priv->instat_urb);
        usb_free_urb(s_priv->indat_urb);
        usb_free_urb(s_priv->glocont_urb);
-       for (i = 0; i < serial->num_ports; ++i) {
-               port = serial->port[i];
-               p_priv = usb_get_serial_port_data(port);
-               usb_free_urb(p_priv->inack_urb);
-               usb_free_urb(p_priv->outcont_urb);
-               for (j = 0; j < 2; j++) {
-                       usb_free_urb(p_priv->in_urbs[j]);
-                       usb_free_urb(p_priv->out_urbs[j]);
-               }
-       }
+
+       kfree(s_priv);
 }
 
-static void keyspan_release(struct usb_serial *serial)
+static int keyspan_port_probe(struct usb_serial_port *port)
 {
-       int                             i;
-       struct usb_serial_port          *port;
-       struct keyspan_serial_private   *s_priv;
+       struct usb_serial *serial = port->serial;
+       struct keyspan_serial_private *s_priv;
+       struct keyspan_port_private *p_priv;
+       const struct keyspan_device_details *d_details;
+       struct callbacks *cback;
+       int endp;
+       int port_num;
+       int i;
 
        s_priv = usb_get_serial_data(serial);
+       d_details = s_priv->device_details;
 
-       kfree(s_priv);
+       p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL);
+       if (!p_priv)
+               return -ENOMEM;
 
-       /* Now free per port private data */
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-               kfree(usb_get_serial_port_data(port));
+       p_priv->device_details = d_details;
+
+       /* Setup values for the various callback routines */
+       cback = &keyspan_callbacks[d_details->msg_format];
+
+       port_num = port->number - port->serial->minor;
+
+       /* Do indat endpoints first, once for each flip */
+       endp = d_details->indat_endpoints[port_num];
+       for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) {
+               p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp,
+                                               USB_DIR_IN, port,
+                                               p_priv->in_buffer[i], 64,
+                                               cback->indat_callback);
+       }
+       /* outdat endpoints also have flip */
+       endp = d_details->outdat_endpoints[port_num];
+       for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) {
+               p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp,
+                                               USB_DIR_OUT, port,
+                                               p_priv->out_buffer[i], 64,
+                                               cback->outdat_callback);
+       }
+       /* inack endpoint */
+       p_priv->inack_urb = keyspan_setup_urb(serial,
+                                       d_details->inack_endpoints[port_num],
+                                       USB_DIR_IN, port,
+                                       p_priv->inack_buffer, 1,
+                                       cback->inack_callback);
+       /* outcont endpoint */
+       p_priv->outcont_urb = keyspan_setup_urb(serial,
+                                       d_details->outcont_endpoints[port_num],
+                                       USB_DIR_OUT, port,
+                                       p_priv->outcont_buffer, 64,
+                                        cback->outcont_callback);
+
+       usb_set_serial_port_data(port, p_priv);
+
+       return 0;
+}
+
+static int keyspan_port_remove(struct usb_serial_port *port)
+{
+       struct keyspan_port_private *p_priv;
+       int i;
+
+       p_priv = usb_get_serial_port_data(port);
+
+       stop_urb(p_priv->inack_urb);
+       stop_urb(p_priv->outcont_urb);
+       for (i = 0; i < 2; i++) {
+               stop_urb(p_priv->in_urbs[i]);
+               stop_urb(p_priv->out_urbs[i]);
+       }
+
+       usb_free_urb(p_priv->inack_urb);
+       usb_free_urb(p_priv->outcont_urb);
+       for (i = 0; i < 2; i++) {
+               usb_free_urb(p_priv->in_urbs[i]);
+               usb_free_urb(p_priv->out_urbs[i]);
        }
+
+       kfree(p_priv);
+
+       return 0;
 }
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
index 0a8a40b..0273dda 100644 (file)
@@ -42,6 +42,8 @@ static void keyspan_dtr_rts           (struct usb_serial_port *port, int on);
 static int  keyspan_startup            (struct usb_serial *serial);
 static void keyspan_disconnect         (struct usb_serial *serial);
 static void keyspan_release            (struct usb_serial *serial);
+static int keyspan_port_probe(struct usb_serial_port *port);
+static int keyspan_port_remove(struct usb_serial_port *port);
 static int  keyspan_write_room         (struct tty_struct *tty);
 
 static int  keyspan_write              (struct tty_struct *tty,
@@ -567,6 +569,8 @@ static struct usb_serial_driver keyspan_1port_device = {
        .attach                 = keyspan_startup,
        .disconnect             = keyspan_disconnect,
        .release                = keyspan_release,
+       .port_probe             = keyspan_port_probe,
+       .port_remove            = keyspan_port_remove,
 };
 
 static struct usb_serial_driver keyspan_2port_device = {
@@ -589,6 +593,8 @@ static struct usb_serial_driver keyspan_2port_device = {
        .attach                 = keyspan_startup,
        .disconnect             = keyspan_disconnect,
        .release                = keyspan_release,
+       .port_probe             = keyspan_port_probe,
+       .port_remove            = keyspan_port_remove,
 };
 
 static struct usb_serial_driver keyspan_4port_device = {
@@ -611,6 +617,8 @@ static struct usb_serial_driver keyspan_4port_device = {
        .attach                 = keyspan_startup,
        .disconnect             = keyspan_disconnect,
        .release                = keyspan_release,
+       .port_probe             = keyspan_port_probe,
+       .port_remove            = keyspan_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
index ca43ecb..bb87e29 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 3f6d737..1f45178 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 5c4d2fb..c9ca7a5 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 f394771..8a20810 100644 (file)
@@ -49,7 +49,8 @@
  * Function prototypes
  */
 static int  mct_u232_startup(struct usb_serial *serial);
-static void mct_u232_release(struct usb_serial *serial);
+static int  mct_u232_port_probe(struct usb_serial_port *port);
+static int  mct_u232_port_remove(struct usb_serial_port *remove);
 static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port);
 static void mct_u232_close(struct usb_serial_port *port);
 static void mct_u232_dtr_rts(struct usb_serial_port *port, int on);
@@ -99,7 +100,8 @@ static struct usb_serial_driver mct_u232_device = {
        .tiocmget =          mct_u232_tiocmget,
        .tiocmset =          mct_u232_tiocmset,
        .attach =            mct_u232_startup,
-       .release =           mct_u232_release,
+       .port_probe =        mct_u232_port_probe,
+       .port_remove =       mct_u232_port_remove,
        .ioctl =             mct_u232_ioctl,
        .get_icount =        mct_u232_get_icount,
 };
@@ -388,18 +390,8 @@ static void mct_u232_msr_to_state(struct usb_serial_port *port,
 
 static int mct_u232_startup(struct usb_serial *serial)
 {
-       struct mct_u232_private *priv;
        struct usb_serial_port *port, *rport;
 
-       priv = kzalloc(sizeof(struct mct_u232_private), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-       spin_lock_init(&priv->lock);
-       init_waitqueue_head(&priv->msr_wait);
-       usb_set_serial_port_data(serial->port[0], priv);
-
-       init_waitqueue_head(&serial->port[0]->write_wait);
-
        /* Puh, that's dirty */
        port = serial->port[0];
        rport = serial->port[1];
@@ -412,18 +404,31 @@ static int mct_u232_startup(struct usb_serial *serial)
        return 0;
 } /* mct_u232_startup */
 
+static int mct_u232_port_probe(struct usb_serial_port *port)
+{
+       struct mct_u232_private *priv;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       spin_lock_init(&priv->lock);
+       init_waitqueue_head(&priv->msr_wait);
+
+       usb_set_serial_port_data(port, priv);
 
-static void mct_u232_release(struct usb_serial *serial)
+       return 0;
+}
+
+static int mct_u232_port_remove(struct usb_serial_port *port)
 {
        struct mct_u232_private *priv;
-       int i;
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               /* My special items, the standard routines free my urbs */
-               priv = usb_get_serial_port_data(serial->port[i]);
-               kfree(priv);
-       }
-} /* mct_u232_release */
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
+}
 
 static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
@@ -515,12 +520,14 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on)
 
 static void mct_u232_close(struct usb_serial_port *port)
 {
-       if (port->serial->dev) {
-               /* shutdown our urbs */
-               usb_kill_urb(port->write_urb);
-               usb_kill_urb(port->read_urb);
-               usb_kill_urb(port->interrupt_in_urb);
-       }
+       /*
+        * Must kill the read urb as it is actually an interrupt urb, which
+        * generic close thus fails to kill.
+        */
+       usb_kill_urb(port->read_urb);
+       usb_kill_urb(port->interrupt_in_urb);
+
+       usb_serial_generic_close(port);
 } /* mct_u232_close */
 
 
index 0b257dd..6f29c74 100644 (file)
@@ -179,16 +179,13 @@ static void metrousb_cleanup(struct usb_serial_port *port)
 {
        dev_dbg(&port->dev, "%s\n", __func__);
 
-       if (port->serial->dev) {
-               /* Shutdown any interrupt in urbs. */
-               if (port->interrupt_in_urb) {
-                       usb_unlink_urb(port->interrupt_in_urb);
-                       usb_kill_urb(port->interrupt_in_urb);
-               }
-
-               /* Send deactivate cmd to device */
+       usb_unlink_urb(port->interrupt_in_urb);
+       usb_kill_urb(port->interrupt_in_urb);
+
+       mutex_lock(&port->serial->disc_mutex);
+       if (!port->serial->disconnected)
                metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port);
-       }
+       mutex_unlock(&port->serial->disc_mutex);
 }
 
 static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port)
@@ -271,51 +268,27 @@ static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int contr
        return retval;
 }
 
-static void metrousb_shutdown(struct usb_serial *serial)
+static int metrousb_port_probe(struct usb_serial_port *port)
 {
-       int i = 0;
+       struct metrousb_private *metro_priv;
 
-       dev_dbg(&serial->dev->dev, "%s\n", __func__);
+       metro_priv = kzalloc(sizeof(*metro_priv), GFP_KERNEL);
+       if (!metro_priv)
+               return -ENOMEM;
 
-       /* Stop reading and writing on all ports. */
-       for (i = 0; i < serial->num_ports; ++i) {
-               /* Close any open urbs. */
-               metrousb_cleanup(serial->port[i]);
+       spin_lock_init(&metro_priv->lock);
 
-               /* Free memory. */
-               kfree(usb_get_serial_port_data(serial->port[i]));
-               usb_set_serial_port_data(serial->port[i], NULL);
+       usb_set_serial_port_data(port, metro_priv);
 
-               dev_dbg(&serial->dev->dev, "%s - freed port number=%d\n",
-                       __func__, serial->port[i]->number);
-       }
+       return 0;
 }
 
-static int metrousb_startup(struct usb_serial *serial)
+static int metrousb_port_remove(struct usb_serial_port *port)
 {
        struct metrousb_private *metro_priv;
-       struct usb_serial_port *port;
-       int i = 0;
 
-       dev_dbg(&serial->dev->dev, "%s\n", __func__);
-
-       /* Loop through the serial ports setting up the private structures.
-        * Currently we only use one port. */
-       for (i = 0; i < serial->num_ports; ++i) {
-               port = serial->port[i];
-
-               /* Declare memory. */
-               metro_priv = kzalloc(sizeof(struct metrousb_private), GFP_KERNEL);
-               if (!metro_priv)
-                       return -ENOMEM;
-
-               /* Initialize memory. */
-               spin_lock_init(&metro_priv->lock);
-               usb_set_serial_port_data(port, metro_priv);
-
-               dev_dbg(&serial->dev->dev, "%s - port number=%d\n ",
-                       __func__, port->number);
-       }
+       metro_priv = usb_get_serial_port_data(port);
+       kfree(metro_priv);
 
        return 0;
 }
@@ -414,8 +387,8 @@ static struct usb_serial_driver metrousb_device = {
        .close                  = metrousb_cleanup,
        .read_int_callback      = metrousb_read_int_callback,
        .write_int_callback     = metrousb_write_int_callback,
-       .attach                 = metrousb_startup,
-       .release                = metrousb_shutdown,
+       .port_probe             = metrousb_port_probe,
+       .port_remove            = metrousb_port_remove,
        .throttle               = metrousb_throttle,
        .unthrottle             = metrousb_unthrottle,
        .tiocmget               = metrousb_tiocmget,
index 1bf1ad0..7526742 100644 (file)
@@ -1966,9 +1966,7 @@ static int mos7720_ioctl(struct tty_struct *tty,
 
 static int mos7720_startup(struct usb_serial *serial)
 {
-       struct moschip_port *mos7720_port;
        struct usb_device *dev;
-       int i;
        char data;
        u16 product;
        int ret_val;
@@ -1999,29 +1997,6 @@ static int mos7720_startup(struct usb_serial *serial)
                serial->port[1]->interrupt_in_buffer = NULL;
        }
 
-
-       /* set up serial port private structures */
-       for (i = 0; i < serial->num_ports; ++i) {
-               mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
-               if (mos7720_port == NULL) {
-                       dev_err(&dev->dev, "%s - Out of memory\n", __func__);
-                       return -ENOMEM;
-               }
-
-               /* Initialize all port interrupt end point to port 0 int
-                * endpoint.  Our device has only one interrupt endpoint
-                * common to all ports */
-               serial->port[i]->interrupt_in_endpointAddress =
-                               serial->port[0]->interrupt_in_endpointAddress;
-
-               mos7720_port->port = serial->port[i];
-               usb_set_serial_port_data(serial->port[i], mos7720_port);
-
-               dev_dbg(&dev->dev, "port number is %d\n", serial->port[i]->number);
-               dev_dbg(&dev->dev, "serial number is %d\n", serial->minor);
-       }
-
-
        /* setting configuration feature to one */
        usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
                        (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5*HZ);
@@ -2049,8 +2024,6 @@ static int mos7720_startup(struct usb_serial *serial)
 
 static void mos7720_release(struct usb_serial *serial)
 {
-       int i;
-
 #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT
        /* close the parallel port */
 
@@ -2089,9 +2062,36 @@ static void mos7720_release(struct usb_serial *serial)
                kref_put(&mos_parport->ref_count, destroy_mos_parport);
        }
 #endif
-       /* free private structure allocated for serial port */
-       for (i = 0; i < serial->num_ports; ++i)
-               kfree(usb_get_serial_port_data(serial->port[i]));
+}
+
+static int mos7720_port_probe(struct usb_serial_port *port)
+{
+       struct moschip_port *mos7720_port;
+
+       mos7720_port = kzalloc(sizeof(*mos7720_port), GFP_KERNEL);
+       if (!mos7720_port)
+               return -ENOMEM;
+
+       /* Initialize all port interrupt end point to port 0 int endpoint.
+        * Our device has only one interrupt endpoint common to all ports.
+        */
+       port->interrupt_in_endpointAddress =
+               port->serial->port[0]->interrupt_in_endpointAddress;
+       mos7720_port->port = port;
+
+       usb_set_serial_port_data(port, mos7720_port);
+
+       return 0;
+}
+
+static int mos7720_port_remove(struct usb_serial_port *port)
+{
+       struct moschip_port *mos7720_port;
+
+       mos7720_port = usb_get_serial_port_data(port);
+       kfree(mos7720_port);
+
+       return 0;
 }
 
 static struct usb_serial_driver moschip7720_2port_driver = {
@@ -2109,6 +2109,8 @@ static struct usb_serial_driver moschip7720_2port_driver = {
        .probe                  = mos77xx_probe,
        .attach                 = mos7720_startup,
        .release                = mos7720_release,
+       .port_probe             = mos7720_port_probe,
+       .port_remove            = mos7720_port_remove,
        .ioctl                  = mos7720_ioctl,
        .tiocmget               = mos7720_tiocmget,
        .tiocmset               = mos7720_tiocmset,
index d6d4eec..1cf3375 100644 (file)
@@ -218,12 +218,10 @@ struct moschip_port {
        int port_num;           /*Actual port number in the device(1,2,etc) */
        struct urb *write_urb;  /* write URB for this port */
        struct urb *read_urb;   /* read URB for this port */
-       struct urb *int_urb;
        __u8 shadowLCR;         /* last LCR value received */
        __u8 shadowMCR;         /* last MCR value received */
        char open;
        char open_ports;
-       char zombie;
        wait_queue_head_t wait_chase;   /* for handling sleeping while waiting for chase to finish */
        wait_queue_head_t delta_msr_wait;       /* for handling sleeping while waiting for msr change to happen */
        int delta_msr_cond;
@@ -478,7 +476,6 @@ static void mos7840_control_callback(struct urb *urb)
        struct moschip_port *mos7840_port;
        struct device *dev = &urb->dev->dev;
        __u8 regval = 0x0;
-       int result = 0;
        int status = urb->status;
 
        mos7840_port = urb->context;
@@ -495,7 +492,7 @@ static void mos7840_control_callback(struct urb *urb)
                return;
        default:
                dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status);
-               goto exit;
+               return;
        }
 
        dev_dbg(dev, "%s urb buffer size is %d\n", __func__, urb->actual_length);
@@ -508,16 +505,6 @@ static void mos7840_control_callback(struct urb *urb)
                mos7840_handle_new_msr(mos7840_port, regval);
        else if (mos7840_port->MsrLsr == 1)
                mos7840_handle_new_lsr(mos7840_port, regval);
-
-exit:
-       spin_lock(&mos7840_port->pool_lock);
-       if (!mos7840_port->zombie)
-               result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC);
-       spin_unlock(&mos7840_port->pool_lock);
-       if (result) {
-               dev_err(dev, "%s - Error %d submitting interrupt urb\n",
-                       __func__, result);
-       }
 }
 
 static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
@@ -686,14 +673,7 @@ static void mos7840_interrupt_callback(struct urb *urb)
                                        wreg = MODEM_STATUS_REGISTER;
                                        break;
                                }
-                               spin_lock(&mos7840_port->pool_lock);
-                               if (!mos7840_port->zombie) {
-                                       rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data);
-                               } else {
-                                       spin_unlock(&mos7840_port->pool_lock);
-                                       return;
-                               }
-                               spin_unlock(&mos7840_port->pool_lock);
+                               rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data);
                        }
                }
        }
@@ -2347,309 +2327,249 @@ static int mos7840_calc_num_ports(struct usb_serial *serial)
        return mos7840_num_ports;
 }
 
-/****************************************************************************
- * mos7840_startup
- ****************************************************************************/
-
-static int mos7840_startup(struct usb_serial *serial)
+static int mos7840_port_probe(struct usb_serial_port *port)
 {
+       struct usb_serial *serial = port->serial;
        struct moschip_port *mos7840_port;
-       struct usb_device *dev;
-       int i, status;
+       int status;
+       int pnum;
        __u16 Data;
 
-       dev = serial->dev;
-
        /* we set up the pointers to the endpoints in the mos7840_open *
         * function, as the structures aren't created yet.             */
 
-       /* set up port private structures */
-       for (i = 0; i < serial->num_ports; ++i) {
-               dev_dbg(&dev->dev, "mos7840_startup: configuring port %d............\n", i);
-               mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
-               if (mos7840_port == NULL) {
-                       dev_err(&dev->dev, "%s - Out of memory\n", __func__);
-                       status = -ENOMEM;
-                       i--; /* don't follow NULL pointer cleaning up */
-                       goto error;
-               }
-
-               /* Initialize all port interrupt end point to port 0 int
-                * endpoint. Our device has only one interrupt end point
-                * common to all port */
-
-               mos7840_port->port = serial->port[i];
-               mos7840_set_port_private(serial->port[i], mos7840_port);
-               spin_lock_init(&mos7840_port->pool_lock);
-
-               /* minor is not initialised until later by
-                * usb-serial.c:get_free_serial() and cannot therefore be used
-                * to index device instances */
-               mos7840_port->port_num = i + 1;
-               dev_dbg(&dev->dev, "serial->port[i]->number = %d\n", serial->port[i]->number);
-               dev_dbg(&dev->dev, "serial->port[i]->serial->minor = %d\n", serial->port[i]->serial->minor);
-               dev_dbg(&dev->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num);
-               dev_dbg(&dev->dev, "serial->minor = %d\n", serial->minor);
-
-               if (mos7840_port->port_num == 1) {
-                       mos7840_port->SpRegOffset = 0x0;
-                       mos7840_port->ControlRegOffset = 0x1;
-                       mos7840_port->DcrRegOffset = 0x4;
-               } else if ((mos7840_port->port_num == 2)
-                          && (serial->num_ports == 4)) {
-                       mos7840_port->SpRegOffset = 0x8;
-                       mos7840_port->ControlRegOffset = 0x9;
-                       mos7840_port->DcrRegOffset = 0x16;
-               } else if ((mos7840_port->port_num == 2)
-                          && (serial->num_ports == 2)) {
-                       mos7840_port->SpRegOffset = 0xa;
-                       mos7840_port->ControlRegOffset = 0xb;
-                       mos7840_port->DcrRegOffset = 0x19;
-               } else if ((mos7840_port->port_num == 3)
-                          && (serial->num_ports == 4)) {
-                       mos7840_port->SpRegOffset = 0xa;
-                       mos7840_port->ControlRegOffset = 0xb;
-                       mos7840_port->DcrRegOffset = 0x19;
-               } else if ((mos7840_port->port_num == 4)
-                          && (serial->num_ports == 4)) {
-                       mos7840_port->SpRegOffset = 0xc;
-                       mos7840_port->ControlRegOffset = 0xd;
-                       mos7840_port->DcrRegOffset = 0x1c;
-               }
-               mos7840_dump_serial_port(serial->port[i], mos7840_port);
-               mos7840_set_port_private(serial->port[i], mos7840_port);
+       pnum = port->number - serial->minor;
 
-               /* enable rx_disable bit in control register */
-               status = mos7840_get_reg_sync(serial->port[i],
-                                mos7840_port->ControlRegOffset, &Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Reading ControlReg failed status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "ControlReg Reading success val is %x, status%d\n", Data, status);
-               Data |= 0x08;   /* setting driver done bit */
-               Data |= 0x04;   /* sp1_bit to have cts change reflect in
-                                  modem status reg */
-
-               /* Data |= 0x20; //rx_disable bit */
-               status = mos7840_set_reg_sync(serial->port[i],
-                                        mos7840_port->ControlRegOffset, Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "ControlReg Writing success(rx_disable) status%d\n", status);
+       dev_dbg(&port->dev, "mos7840_startup: configuring port %d\n", pnum);
+       mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
+       if (mos7840_port == NULL) {
+               dev_err(&port->dev, "%s - Out of memory\n", __func__);
+               return -ENOMEM;
+       }
 
-               /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2
-                  and 0x24 in DCR3 */
-               Data = 0x01;
-               status = mos7840_set_reg_sync(serial->port[i],
-                        (__u16) (mos7840_port->DcrRegOffset + 0), Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing DCR0 failed status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "DCR0 Writing success status%d\n", status);
+       /* Initialize all port interrupt end point to port 0 int
+        * endpoint. Our device has only one interrupt end point
+        * common to all port */
+
+       mos7840_port->port = port;
+       mos7840_set_port_private(port, mos7840_port);
+       spin_lock_init(&mos7840_port->pool_lock);
+
+       /* minor is not initialised until later by
+        * usb-serial.c:get_free_serial() and cannot therefore be used
+        * to index device instances */
+       mos7840_port->port_num = pnum + 1;
+       dev_dbg(&port->dev, "port->number = %d\n", port->number);
+       dev_dbg(&port->dev, "port->serial->minor = %d\n", port->serial->minor);
+       dev_dbg(&port->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num);
+       dev_dbg(&port->dev, "serial->minor = %d\n", serial->minor);
+
+       if (mos7840_port->port_num == 1) {
+               mos7840_port->SpRegOffset = 0x0;
+               mos7840_port->ControlRegOffset = 0x1;
+               mos7840_port->DcrRegOffset = 0x4;
+       } else if ((mos7840_port->port_num == 2) && (serial->num_ports == 4)) {
+               mos7840_port->SpRegOffset = 0x8;
+               mos7840_port->ControlRegOffset = 0x9;
+               mos7840_port->DcrRegOffset = 0x16;
+       } else if ((mos7840_port->port_num == 2) && (serial->num_ports == 2)) {
+               mos7840_port->SpRegOffset = 0xa;
+               mos7840_port->ControlRegOffset = 0xb;
+               mos7840_port->DcrRegOffset = 0x19;
+       } else if ((mos7840_port->port_num == 3) && (serial->num_ports == 4)) {
+               mos7840_port->SpRegOffset = 0xa;
+               mos7840_port->ControlRegOffset = 0xb;
+               mos7840_port->DcrRegOffset = 0x19;
+       } else if ((mos7840_port->port_num == 4) && (serial->num_ports == 4)) {
+               mos7840_port->SpRegOffset = 0xc;
+               mos7840_port->ControlRegOffset = 0xd;
+               mos7840_port->DcrRegOffset = 0x1c;
+       }
+       mos7840_dump_serial_port(port, mos7840_port);
+       mos7840_set_port_private(port, mos7840_port);
+
+       /* enable rx_disable bit in control register */
+       status = mos7840_get_reg_sync(port,
+                       mos7840_port->ControlRegOffset, &Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Reading ControlReg failed status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "ControlReg Reading success val is %x, status%d\n", Data, status);
+       Data |= 0x08;   /* setting driver done bit */
+       Data |= 0x04;   /* sp1_bit to have cts change reflect in
+                          modem status reg */
 
-               Data = 0x05;
-               status = mos7840_set_reg_sync(serial->port[i],
-                        (__u16) (mos7840_port->DcrRegOffset + 1), Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing DCR1 failed status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "DCR1 Writing success status%d\n", status);
+       /* Data |= 0x20; //rx_disable bit */
+       status = mos7840_set_reg_sync(port,
+                       mos7840_port->ControlRegOffset, Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "ControlReg Writing success(rx_disable) status%d\n", status);
 
-               Data = 0x24;
-               status = mos7840_set_reg_sync(serial->port[i],
-                        (__u16) (mos7840_port->DcrRegOffset + 2), Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing DCR2 failed status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "DCR2 Writing success status%d\n", status);
+       /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2
+          and 0x24 in DCR3 */
+       Data = 0x01;
+       status = mos7840_set_reg_sync(port,
+                       (__u16) (mos7840_port->DcrRegOffset + 0), Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing DCR0 failed status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "DCR0 Writing success status%d\n", status);
 
-               /* write values in clkstart0x0 and clkmulti 0x20 */
-               Data = 0x0;
-               status = mos7840_set_reg_sync(serial->port[i],
-                                        CLK_START_VALUE_REGISTER, Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status);
+       Data = 0x05;
+       status = mos7840_set_reg_sync(port,
+                       (__u16) (mos7840_port->DcrRegOffset + 1), Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing DCR1 failed status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "DCR1 Writing success status%d\n", status);
 
-               Data = 0x20;
-               status = mos7840_set_reg_sync(serial->port[i],
-                                       CLK_MULTI_REGISTER, Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status);
-                       goto error;
-               } else
-                       dev_dbg(&dev->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status);
+       Data = 0x24;
+       status = mos7840_set_reg_sync(port,
+                       (__u16) (mos7840_port->DcrRegOffset + 2), Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing DCR2 failed status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "DCR2 Writing success status%d\n", status);
 
-               /* write value 0x0 to scratchpad register */
-               Data = 0x00;
-               status = mos7840_set_uart_reg(serial->port[i],
-                                               SCRATCH_PAD_REGISTER, Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status);
+       /* write values in clkstart0x0 and clkmulti 0x20 */
+       Data = 0x0;
+       status = mos7840_set_reg_sync(port, CLK_START_VALUE_REGISTER, Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status);
 
-               /* Zero Length flag register */
-               if ((mos7840_port->port_num != 1)
-                   && (serial->num_ports == 2)) {
+       Data = 0x20;
+       status = mos7840_set_reg_sync(port, CLK_MULTI_REGISTER, Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status);
+               goto error;
+       } else
+               dev_dbg(&port->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status);
 
-                       Data = 0xff;
-                       status = mos7840_set_reg_sync(serial->port[i],
-                                     (__u16) (ZLP_REG1 +
-                                     ((__u16)mos7840_port->port_num)), Data);
-                       dev_dbg(&dev->dev, "ZLIP offset %x\n",
+       /* write value 0x0 to scratchpad register */
+       Data = 0x00;
+       status = mos7840_set_uart_reg(port, SCRATCH_PAD_REGISTER, Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status);
+
+       /* Zero Length flag register */
+       if ((mos7840_port->port_num != 1) && (serial->num_ports == 2)) {
+               Data = 0xff;
+               status = mos7840_set_reg_sync(port,
+                               (__u16) (ZLP_REG1 +
+                                       ((__u16)mos7840_port->port_num)), Data);
+               dev_dbg(&port->dev, "ZLIP offset %x\n",
                                (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num)));
-                       if (status < 0) {
-                               dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 2, status);
-                               break;
-                       } else
-                               dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 2, status);
-               } else {
-                       Data = 0xff;
-                       status = mos7840_set_reg_sync(serial->port[i],
-                             (__u16) (ZLP_REG1 +
-                             ((__u16)mos7840_port->port_num) - 0x1), Data);
-                       dev_dbg(&dev->dev, "ZLIP offset %x\n",
+               if (status < 0) {
+                       dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 2, status);
+                       goto out;
+               } else
+                       dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 2, status);
+       } else {
+               Data = 0xff;
+               status = mos7840_set_reg_sync(port,
+                               (__u16) (ZLP_REG1 +
+                                       ((__u16)mos7840_port->port_num) - 0x1), Data);
+               dev_dbg(&port->dev, "ZLIP offset %x\n",
                                (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num) - 0x1));
-                       if (status < 0) {
-                               dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 1, status);
-                               break;
-                       } else
-                               dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 1, status);
+               if (status < 0) {
+                       dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 1, status);
+                       goto out;
+               } else
+                       dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 1, status);
 
-               }
-               mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL);
-               mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL);
-               mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest),
-                                                               GFP_KERNEL);
-               if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf ||
-                                                       !mos7840_port->dr) {
-                       status = -ENOMEM;
-                       goto error;
-               }
+       }
+       mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL);
+       mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL);
+       mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest),
+                       GFP_KERNEL);
+       if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf ||
+                       !mos7840_port->dr) {
+               status = -ENOMEM;
+               goto error;
+       }
 
-               mos7840_port->has_led = false;
+       mos7840_port->has_led = false;
 
-               /* Initialize LED timers */
-               if (device_type == MOSCHIP_DEVICE_ID_7810) {
-                       mos7840_port->has_led = true;
+       /* Initialize LED timers */
+       if (device_type == MOSCHIP_DEVICE_ID_7810) {
+               mos7840_port->has_led = true;
 
-                       init_timer(&mos7840_port->led_timer1);
-                       mos7840_port->led_timer1.function = mos7840_led_off;
-                       mos7840_port->led_timer1.expires =
-                                       jiffies + msecs_to_jiffies(LED_ON_MS);
-                       mos7840_port->led_timer1.data =
-                                               (unsigned long)mos7840_port;
+               init_timer(&mos7840_port->led_timer1);
+               mos7840_port->led_timer1.function = mos7840_led_off;
+               mos7840_port->led_timer1.expires =
+                       jiffies + msecs_to_jiffies(LED_ON_MS);
+               mos7840_port->led_timer1.data = (unsigned long)mos7840_port;
 
-                       init_timer(&mos7840_port->led_timer2);
-                       mos7840_port->led_timer2.function =
-                                               mos7840_led_flag_off;
-                       mos7840_port->led_timer2.expires =
-                                       jiffies + msecs_to_jiffies(LED_OFF_MS);
-                       mos7840_port->led_timer2.data =
-                                               (unsigned long)mos7840_port;
+               init_timer(&mos7840_port->led_timer2);
+               mos7840_port->led_timer2.function = mos7840_led_flag_off;
+               mos7840_port->led_timer2.expires =
+                       jiffies + msecs_to_jiffies(LED_OFF_MS);
+               mos7840_port->led_timer2.data = (unsigned long)mos7840_port;
 
-                       mos7840_port->led_flag = false;
+               mos7840_port->led_flag = false;
 
-                       /* Turn off LED */
-                       mos7840_set_led_sync(serial->port[i],
-                                               MODEM_CONTROL_REGISTER, 0x0300);
-               }
+               /* Turn off LED */
+               mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300);
        }
+out:
+       if (pnum == serial->num_ports - 1) {
+               /* Zero Length flag enable */
+               Data = 0x0f;
+               status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data);
+               if (status < 0) {
+                       dev_dbg(&port->dev, "Writing ZLP_REG5 failed status-0x%x\n", status);
+                       goto error;
+               } else
+                       dev_dbg(&port->dev, "ZLP_REG5 Writing success status%d\n", status);
 
-       /* Zero Length flag enable */
-       Data = 0x0f;
-       status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data);
-       if (status < 0) {
-               dev_dbg(&dev->dev, "Writing ZLP_REG5 failed status-0x%x\n", status);
-               goto error;
-       } else
-               dev_dbg(&dev->dev, "ZLP_REG5 Writing success status%d\n", status);
-
-       /* setting configuration feature to one */
-       usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-                       (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, MOS_WDR_TIMEOUT);
+               /* setting configuration feature to one */
+               usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+                               0x03, 0x00, 0x01, 0x00, NULL, 0x00,
+                               MOS_WDR_TIMEOUT);
+       }
        return 0;
 error:
-       for (/* nothing */; i >= 0; i--) {
-               mos7840_port = mos7840_get_port_private(serial->port[i]);
+       kfree(mos7840_port->dr);
+       kfree(mos7840_port->ctrl_buf);
+       usb_free_urb(mos7840_port->control_urb);
+       kfree(mos7840_port);
 
-               kfree(mos7840_port->dr);
-               kfree(mos7840_port->ctrl_buf);
-               usb_free_urb(mos7840_port->control_urb);
-               kfree(mos7840_port);
-               serial->port[i] = NULL;
-       }
        return status;
 }
 
-/****************************************************************************
- * mos7840_disconnect
- *     This function is called whenever the device is removed from the usb bus.
- ****************************************************************************/
-
-static void mos7840_disconnect(struct usb_serial *serial)
+static int mos7840_port_remove(struct usb_serial_port *port)
 {
-       int i;
-       unsigned long flags;
        struct moschip_port *mos7840_port;
 
-       /* check for the ports to be closed,close the ports and disconnect */
+       mos7840_port = mos7840_get_port_private(port);
 
-       /* free private structure allocated for serial port  *
-        * stop reads and writes on all ports                */
+       if (mos7840_port->has_led) {
+               /* Turn off LED */
+               mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300);
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               mos7840_port = mos7840_get_port_private(serial->port[i]);
-               if (mos7840_port) {
-                       spin_lock_irqsave(&mos7840_port->pool_lock, flags);
-                       mos7840_port->zombie = 1;
-                       spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
-                       usb_kill_urb(mos7840_port->control_urb);
-               }
+               del_timer_sync(&mos7840_port->led_timer1);
+               del_timer_sync(&mos7840_port->led_timer2);
        }
-}
-
-/****************************************************************************
- * mos7840_release
- *     This function is called when the usb_serial structure is freed.
- ****************************************************************************/
-
-static void mos7840_release(struct usb_serial *serial)
-{
-       int i;
-       struct moschip_port *mos7840_port;
-
-       /* check for the ports to be closed,close the ports and disconnect */
+       usb_kill_urb(mos7840_port->control_urb);
+       usb_free_urb(mos7840_port->control_urb);
+       kfree(mos7840_port->ctrl_buf);
+       kfree(mos7840_port->dr);
+       kfree(mos7840_port);
 
-       /* free private structure allocated for serial port  *
-        * stop reads and writes on all ports                */
-
-       for (i = 0; i < serial->num_ports; ++i) {
-               mos7840_port = mos7840_get_port_private(serial->port[i]);
-               if (mos7840_port) {
-                       if (mos7840_port->has_led) {
-                               /* Turn off LED */
-                               mos7840_set_led_sync(mos7840_port->port,
-                                               MODEM_CONTROL_REGISTER, 0x0300);
-
-                               del_timer_sync(&mos7840_port->led_timer1);
-                               del_timer_sync(&mos7840_port->led_timer2);
-                       }
-                       kfree(mos7840_port->ctrl_buf);
-                       kfree(mos7840_port->dr);
-                       kfree(mos7840_port);
-               }
-       }
+       return 0;
 }
 
 static struct usb_serial_driver moschip7840_4port_device = {
@@ -2677,9 +2597,8 @@ static struct usb_serial_driver moschip7840_4port_device = {
        .tiocmget = mos7840_tiocmget,
        .tiocmset = mos7840_tiocmset,
        .get_icount = mos7840_get_icount,
-       .attach = mos7840_startup,
-       .disconnect = mos7840_disconnect,
-       .release = mos7840_release,
+       .port_probe = mos7840_port_probe,
+       .port_remove = mos7840_port_remove,
        .read_bulk_callback = mos7840_bulk_in_callback,
        .read_int_callback = mos7840_interrupt_callback,
 };
index 6def58b..9ab73d2 100644 (file)
@@ -44,8 +44,8 @@ static int  omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
                                const unsigned char *buf, int count);
 static int  omninet_write_room(struct tty_struct *tty);
 static void omninet_disconnect(struct usb_serial *serial);
-static void omninet_release(struct usb_serial *serial);
-static int omninet_attach(struct usb_serial *serial);
+static int omninet_port_probe(struct usb_serial_port *port);
+static int omninet_port_remove(struct usb_serial_port *port);
 
 static const struct usb_device_id id_table[] = {
        { USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) },
@@ -62,7 +62,8 @@ static struct usb_serial_driver zyxel_omninet_device = {
        .description =          "ZyXEL - omni.net lcd plus usb",
        .id_table =             id_table,
        .num_ports =            1,
-       .attach =               omninet_attach,
+       .port_probe =           omninet_port_probe,
+       .port_remove =          omninet_port_remove,
        .open =                 omninet_open,
        .close =                omninet_close,
        .write =                omninet_write,
@@ -70,7 +71,6 @@ static struct usb_serial_driver zyxel_omninet_device = {
        .read_bulk_callback =   omninet_read_bulk_callback,
        .write_bulk_callback =  omninet_write_bulk_callback,
        .disconnect =           omninet_disconnect,
-       .release =              omninet_release,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
@@ -112,18 +112,26 @@ struct omninet_data {
        __u8    od_outseq;      /* Sequence number for bulk_out URBs */
 };
 
-static int omninet_attach(struct usb_serial *serial)
+static int omninet_port_probe(struct usb_serial_port *port)
 {
        struct omninet_data *od;
-       struct usb_serial_port *port = serial->port[0];
 
        od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL);
-       if (!od) {
-               dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n",
-                       __func__, sizeof(struct omninet_data));
+       if (!od)
                return -ENOMEM;
-       }
+
        usb_set_serial_port_data(port, od);
+
+       return 0;
+}
+
+static int omninet_port_remove(struct usb_serial_port *port)
+{
+       struct omninet_data *od;
+
+       od = usb_get_serial_port_data(port);
+       kfree(od);
+
        return 0;
 }
 
@@ -279,14 +287,6 @@ static void omninet_disconnect(struct usb_serial *serial)
        usb_kill_urb(wport->write_urb);
 }
 
-
-static void omninet_release(struct usb_serial *serial)
-{
-       struct usb_serial_port *port = serial->port[0];
-
-       kfree(usb_get_serial_port_data(port));
-}
-
 module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
index 41b1647..6aba731 100644 (file)
@@ -155,7 +155,11 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,
 {
        struct usb_serial *serial = port->serial;
        int retval;
-       u8 buffer[2];
+       u8 *buffer;
+
+       buffer = kzalloc(1, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
 
        buffer[0] = val;
        /* Send the message to the vendor control endpoint
@@ -164,6 +168,7 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,
                                requesttype,
                                USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
                                0, 0, buffer, 1, 0);
+       kfree(buffer);
 
        return retval;
 }
@@ -281,7 +286,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
        if (!dr) {
                dev_err(&port->dev, "out of memory\n");
                count = -ENOMEM;
-               goto error;
+               goto error_no_dr;
        }
 
        dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT;
@@ -311,6 +316,8 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
 
        return count;
 error:
+       kfree(dr);
+error_no_dr:
        usb_free_urb(urb);
 error_no_urb:
        kfree(buffer);
index 30cff03..edc64bb 100644 (file)
@@ -47,6 +47,7 @@
 /* Function prototypes */
 static int  option_probe(struct usb_serial *serial,
                        const struct usb_device_id *id);
+static int option_attach(struct usb_serial *serial);
 static void option_release(struct usb_serial *serial);
 static int option_send_setup(struct usb_serial_port *port);
 static void option_instat_callback(struct urb *urb);
@@ -157,6 +158,7 @@ static void option_instat_callback(struct urb *urb);
 #define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED        0x8001
 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED        0x9000
 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED        0x9001
+#define NOVATELWIRELESS_PRODUCT_E362           0x9010
 #define NOVATELWIRELESS_PRODUCT_G1             0xA001
 #define NOVATELWIRELESS_PRODUCT_G1_M           0xA002
 #define NOVATELWIRELESS_PRODUCT_G2             0xA010
@@ -192,6 +194,9 @@ static void option_instat_callback(struct urb *urb);
 #define DELL_PRODUCT_5730_MINICARD_TELUS       0x8181
 #define DELL_PRODUCT_5730_MINICARD_VZW         0x8182
 
+#define DELL_PRODUCT_5800_MINICARD_VZW         0x8195  /* Novatel E362 */
+#define DELL_PRODUCT_5800_V2_MINICARD_VZW      0x8196  /* Novatel E362 */
+
 #define KYOCERA_VENDOR_ID                      0x0c88
 #define KYOCERA_PRODUCT_KPC650                 0x17da
 #define KYOCERA_PRODUCT_KPC680                 0x180a
@@ -282,6 +287,7 @@ static void option_instat_callback(struct urb *urb);
 /* ALCATEL PRODUCTS */
 #define ALCATEL_VENDOR_ID                      0x1bbb
 #define ALCATEL_PRODUCT_X060S_X200             0x0000
+#define ALCATEL_PRODUCT_X220_X500D             0x0017
 
 #define PIRELLI_VENDOR_ID                      0x1266
 #define PIRELLI_PRODUCT_C100_1                 0x1002
@@ -503,11 +509,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) },
@@ -697,6 +711,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) },
        /* Novatel Ovation MC551 a.k.a. Verizon USB551L */
        { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E362, 0xff, 0xff, 0xff) },
 
        { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) },
        { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) },
@@ -719,6 +734,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_SPRINT) },      /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
        { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_TELUS) },       /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
        { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_VZW) },         /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
+       { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_MINICARD_VZW, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_V2_MINICARD_VZW, 0xff, 0xff, 0xff) },
        { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) },   /* ADU-E100, ADU-310 */
        { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
        { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) },
@@ -853,13 +870,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 +895,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 +904,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 +1035,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 +1097,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 +1118,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) },
@@ -1112,6 +1165,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200),
          .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist
        },
+       { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) },
        { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
        { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
        { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14),
@@ -1244,8 +1298,9 @@ static struct usb_serial_driver option_1port_device = {
        .tiocmget          = usb_wwan_tiocmget,
        .tiocmset          = usb_wwan_tiocmset,
        .ioctl             = usb_wwan_ioctl,
-       .attach            = usb_wwan_startup,
+       .attach            = option_attach,
        .release           = option_release,
+       .port_probe        = usb_wwan_port_probe,
        .port_remove       = usb_wwan_port_remove,
        .read_int_callback = option_instat_callback,
 #ifdef CONFIG_PM
@@ -1291,8 +1346,6 @@ static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason,
 static int option_probe(struct usb_serial *serial,
                        const struct usb_device_id *id)
 {
-       struct usb_wwan_intf_private *data;
-       struct option_private *priv;
        struct usb_interface_descriptor *iface_desc =
                                &serial->interface->cur_altsetting->desc;
        struct usb_device_descriptor *dev_desc = &serial->dev->descriptor;
@@ -1330,6 +1383,19 @@ static int option_probe(struct usb_serial *serial,
                iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)
                return -ENODEV;
 
+       /* Store device id so we can use it during attach. */
+       usb_set_serial_data(serial, (void *)id);
+
+       return 0;
+}
+
+static int option_attach(struct usb_serial *serial)
+{
+       struct usb_interface_descriptor *iface_desc;
+       const struct usb_device_id *id;
+       struct usb_wwan_intf_private *data;
+       struct option_private *priv;
+
        data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
@@ -1340,6 +1406,10 @@ static int option_probe(struct usb_serial *serial,
                return -ENOMEM;
        }
 
+       /* Retrieve device id stored at probe. */
+       id = usb_get_serial_data(serial);
+       iface_desc = &serial->interface->cur_altsetting->desc;
+
        priv->bInterfaceNumber = iface_desc->bInterfaceNumber;
        data->private = priv;
 
index 933241f..cee9a52 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 892ebdc..6002419 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 c3ddb65..aa148c2 100644 (file)
@@ -138,7 +138,6 @@ MODULE_DEVICE_TABLE(usb, id_table);
 
 static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
 {
-       struct usb_wwan_intf_private *data;
        struct usb_host_interface *intf = serial->interface->cur_altsetting;
        struct device *dev = &serial->dev->dev;
        int retval = -ENODEV;
@@ -154,13 +153,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
        ifnum = intf->desc.bInterfaceNumber;
        dev_dbg(dev, "This Interface = %d\n", ifnum);
 
-       data = kzalloc(sizeof(struct usb_wwan_intf_private),
-                                        GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-
-       spin_lock_init(&data->susp_lock);
-
        if (nintf == 1) {
                /* QDL mode */
                /* Gobi 2000 has a single altsetting, older ones have two */
@@ -253,20 +245,28 @@ done:
                }
        }
 
-       /* Set serial->private if not returning error */
-       if (retval == 0)
-               usb_set_serial_data(serial, data);
-       else
-               kfree(data);
-
        return retval;
 }
 
+static int qc_attach(struct usb_serial *serial)
+{
+       struct usb_wwan_intf_private *data;
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       spin_lock_init(&data->susp_lock);
+
+       usb_set_serial_data(serial, data);
+
+       return 0;
+}
+
 static void qc_release(struct usb_serial *serial)
 {
        struct usb_wwan_intf_private *priv = usb_get_serial_data(serial);
 
-       /* Free the private data allocated in qcprobe */
        usb_set_serial_data(serial, NULL);
        kfree(priv);
 }
@@ -285,8 +285,9 @@ static struct usb_serial_driver qcdevice = {
        .write               = usb_wwan_write,
        .write_room          = usb_wwan_write_room,
        .chars_in_buffer     = usb_wwan_chars_in_buffer,
-       .attach              = usb_wwan_startup,
+       .attach              = qc_attach,
        .release             = qc_release,
+       .port_probe          = usb_wwan_port_probe,
        .port_remove         = usb_wwan_port_remove,
 #ifdef CONFIG_PM
        .suspend             = usb_wwan_suspend,
index 2cdfdcc..ffcfc96 100644 (file)
@@ -143,12 +143,12 @@ static void qt2_read_bulk_callback(struct urb *urb);
 
 static void qt2_release(struct usb_serial *serial)
 {
-       int i;
+       struct qt2_serial_private *serial_priv;
 
-       kfree(usb_get_serial_data(serial));
+       serial_priv = usb_get_serial_data(serial);
 
-       for (i = 0; i < serial->num_ports; i++)
-               kfree(usb_get_serial_port_data(serial->port[i]));
+       usb_free_urb(serial_priv->read_urb);
+       kfree(serial_priv);
 }
 
 static inline int calc_baud_divisor(int baudrate)
@@ -423,11 +423,16 @@ static void qt2_close(struct usb_serial_port *port)
        port_priv->is_open = false;
 
        spin_lock_irqsave(&port_priv->urb_lock, flags);
-       if (port_priv->write_urb->status == -EINPROGRESS)
-               usb_kill_urb(port_priv->write_urb);
+       usb_kill_urb(port_priv->write_urb);
        port_priv->urb_in_use = false;
        spin_unlock_irqrestore(&port_priv->urb_lock, flags);
 
+       mutex_lock(&port->serial->disc_mutex);
+       if (port->serial->disconnected) {
+               mutex_unlock(&port->serial->disc_mutex);
+               return;
+       }
+
        /* flush the port transmit buffer */
        i = usb_control_msg(serial->dev,
                            usb_rcvctrlpipe(serial->dev, 0),
@@ -459,26 +464,14 @@ static void qt2_close(struct usb_serial_port *port)
                dev_err(&port->dev, "%s - close port failed %i\n",
                        __func__, i);
 
+       mutex_unlock(&port->serial->disc_mutex);
 }
 
 static void qt2_disconnect(struct usb_serial *serial)
 {
        struct qt2_serial_private *serial_priv = usb_get_serial_data(serial);
-       struct qt2_port_private *port_priv;
-       int i;
-
-       if (serial_priv->read_urb->status == -EINPROGRESS)
-               usb_kill_urb(serial_priv->read_urb);
-
-       usb_free_urb(serial_priv->read_urb);
 
-       for (i = 0; i < serial->num_ports; i++) {
-               port_priv = usb_get_serial_port_data(serial->port[i]);
-
-               if (port_priv->write_urb->status == -EINPROGRESS)
-                       usb_kill_urb(port_priv->write_urb);
-               usb_free_urb(port_priv->write_urb);
-       }
+       usb_kill_urb(serial_priv->read_urb);
 }
 
 static int get_serial_info(struct usb_serial_port *port,
@@ -773,11 +766,9 @@ static void qt2_read_bulk_callback(struct urb *urb)
 
 static int qt2_setup_urbs(struct usb_serial *serial)
 {
-       struct usb_serial_port *port;
        struct usb_serial_port *port0;
        struct qt2_serial_private *serial_priv;
-       struct qt2_port_private *port_priv;
-       int pcount, status;
+       int status;
 
        port0 = serial->port[0];
 
@@ -795,46 +786,21 @@ static int qt2_setup_urbs(struct usb_serial *serial)
                          sizeof(serial_priv->read_buffer),
                          qt2_read_bulk_callback, serial);
 
-       /* setup write_urb for each port */
-       for (pcount = 0; pcount < serial->num_ports; pcount++) {
-
-               port = serial->port[pcount];
-               port_priv = usb_get_serial_port_data(port);
-
-               port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL);
-               if (!port_priv->write_urb) {
-                       dev_err(&serial->dev->dev,
-                               "failed to alloc write_urb for port %i\n",
-                               pcount);
-                       return -ENOMEM;
-               }
-
-               usb_fill_bulk_urb(port_priv->write_urb,
-                                 serial->dev,
-                                 usb_sndbulkpipe(serial->dev,
-                                                 port0->
-                                                 bulk_out_endpointAddress),
-                                 port_priv->write_buffer,
-                                 sizeof(port_priv->write_buffer),
-                                 qt2_write_bulk_callback, port);
-       }
-
        status = usb_submit_urb(serial_priv->read_urb, GFP_KERNEL);
        if (status != 0) {
                dev_err(&serial->dev->dev,
                        "%s - submit read urb failed %i\n", __func__, status);
+               usb_free_urb(serial_priv->read_urb);
                return status;
        }
 
        return 0;
-
 }
 
 static int qt2_attach(struct usb_serial *serial)
 {
        struct qt2_serial_private *serial_priv;
-       struct qt2_port_private *port_priv;
-       int status, pcount;
+       int status;
 
        /* power on unit */
        status = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
@@ -854,26 +820,6 @@ static int qt2_attach(struct usb_serial *serial)
 
        usb_set_serial_data(serial, serial_priv);
 
-       for (pcount = 0; pcount < serial->num_ports; pcount++) {
-               port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
-               if (!port_priv) {
-                       dev_err(&serial->dev->dev,
-                               "%s- kmalloc(%Zd) failed.\n", __func__,
-                               sizeof(*port_priv));
-                       pcount--;
-                       status = -ENOMEM;
-                       goto attach_failed;
-               }
-
-               spin_lock_init(&port_priv->lock);
-               spin_lock_init(&port_priv->urb_lock);
-               init_waitqueue_head(&port_priv->delta_msr_wait);
-
-               port_priv->port = serial->port[pcount];
-
-               usb_set_serial_port_data(serial->port[pcount], port_priv);
-       }
-
        status = qt2_setup_urbs(serial);
        if (status != 0)
                goto attach_failed;
@@ -881,14 +827,53 @@ static int qt2_attach(struct usb_serial *serial)
        return 0;
 
 attach_failed:
-       for (/* empty */; pcount >= 0; pcount--) {
-               port_priv = usb_get_serial_port_data(serial->port[pcount]);
-               kfree(port_priv);
-       }
        kfree(serial_priv);
        return status;
 }
 
+static int qt2_port_probe(struct usb_serial_port *port)
+{
+       struct usb_serial *serial = port->serial;
+       struct qt2_port_private *port_priv;
+       u8 bEndpointAddress;
+
+       port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
+       if (!port_priv)
+               return -ENOMEM;
+
+       spin_lock_init(&port_priv->lock);
+       spin_lock_init(&port_priv->urb_lock);
+       init_waitqueue_head(&port_priv->delta_msr_wait);
+       port_priv->port = port;
+
+       port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!port_priv->write_urb) {
+               kfree(port_priv);
+               return -ENOMEM;
+       }
+       bEndpointAddress = serial->port[0]->bulk_out_endpointAddress;
+       usb_fill_bulk_urb(port_priv->write_urb, serial->dev,
+                               usb_sndbulkpipe(serial->dev, bEndpointAddress),
+                               port_priv->write_buffer,
+                               sizeof(port_priv->write_buffer),
+                               qt2_write_bulk_callback, port);
+
+       usb_set_serial_port_data(port, port_priv);
+
+       return 0;
+}
+
+static int qt2_port_remove(struct usb_serial_port *port)
+{
+       struct qt2_port_private *port_priv;
+
+       port_priv = usb_get_serial_port_data(port);
+       usb_free_urb(port_priv->write_urb);
+       kfree(port_priv);
+
+       return 0;
+}
+
 static int qt2_tiocmget(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
@@ -1127,6 +1112,8 @@ static struct usb_serial_driver qt2_device = {
        .attach              = qt2_attach,
        .release             = qt2_release,
        .disconnect          = qt2_disconnect,
+       .port_probe          = qt2_port_probe,
+       .port_remove         = qt2_port_remove,
        .dtr_rts             = qt2_dtr_rts,
        .break_ctl           = qt2_break_ctl,
        .tiocmget            = qt2_tiocmget,
index 01d882c..270860f 100644 (file)
@@ -161,7 +161,6 @@ static int sierra_probe(struct usb_serial *serial,
 {
        int result = 0;
        struct usb_device *udev;
-       struct sierra_intf_private *data;
        u8 ifnum;
 
        udev = serial->dev;
@@ -188,11 +187,6 @@ static int sierra_probe(struct usb_serial *serial,
                return -ENODEV;
        }
 
-       data = serial->private = kzalloc(sizeof(struct sierra_intf_private), GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-       spin_lock_init(&data->susp_lock);
-
        return result;
 }
 
@@ -884,11 +878,15 @@ static void sierra_dtr_rts(struct usb_serial_port *port, int on)
 
 static int sierra_startup(struct usb_serial *serial)
 {
-       struct usb_serial_port *port;
-       struct sierra_port_private *portdata;
-       struct sierra_iface_info *himemoryp = NULL;
-       int i;
-       u8 ifnum;
+       struct sierra_intf_private *intfdata;
+
+       intfdata = kzalloc(sizeof(*intfdata), GFP_KERNEL);
+       if (!intfdata)
+               return -ENOMEM;
+
+       spin_lock_init(&intfdata->susp_lock);
+
+       usb_set_serial_data(serial, intfdata);
 
        /* Set Device mode to D0 */
        sierra_set_power_state(serial->dev, 0x0000);
@@ -897,68 +895,71 @@ static int sierra_startup(struct usb_serial *serial)
        if (nmea)
                sierra_vsc_set_nmea(serial->dev, 1);
 
-       /* Now setup per port private data */
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-               portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
-               if (!portdata) {
-                       dev_dbg(&port->dev, "%s: kmalloc for "
-                               "sierra_port_private (%d) failed!\n",
-                               __func__, i);
-                       return -ENOMEM;
-               }
-               spin_lock_init(&portdata->lock);
-               init_usb_anchor(&portdata->active);
-               init_usb_anchor(&portdata->delayed);
-               ifnum = i;
-               /* Assume low memory requirements */
-               portdata->num_out_urbs = N_OUT_URB;
-               portdata->num_in_urbs  = N_IN_URB;
-
-               /* Determine actual memory requirements */
-               if (serial->num_ports == 1) {
-                       /* Get interface number for composite device */
-                       ifnum = sierra_calc_interface(serial);
-                       himemoryp =
-                           (struct sierra_iface_info *)&typeB_interface_list;
-                       if (is_himemory(ifnum, himemoryp)) {
-                               portdata->num_out_urbs = N_OUT_URB_HM;
-                               portdata->num_in_urbs  = N_IN_URB_HM;
-                       }
-               }
-               else {
-                       himemoryp =
-                           (struct sierra_iface_info *)&typeA_interface_list;
-                       if (is_himemory(i, himemoryp)) {
-                               portdata->num_out_urbs = N_OUT_URB_HM;
-                               portdata->num_in_urbs  = N_IN_URB_HM;
-                       }
-               }
-               dev_dbg(&serial->dev->dev,
-                       "Memory usage (urbs) interface #%d, in=%d, out=%d\n",
-                       ifnum,portdata->num_in_urbs, portdata->num_out_urbs );
-               /* Set the port private data pointer */
-               usb_set_serial_port_data(port, portdata);
-       }
-
        return 0;
 }
 
 static void sierra_release(struct usb_serial *serial)
 {
-       int i;
-       struct usb_serial_port *port;
+       struct sierra_intf_private *intfdata;
+
+       intfdata = usb_get_serial_data(serial);
+       kfree(intfdata);
+}
+
+static int sierra_port_probe(struct usb_serial_port *port)
+{
+       struct usb_serial *serial = port->serial;
        struct sierra_port_private *portdata;
+       const struct sierra_iface_info *himemoryp;
+       u8 ifnum;
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               port = serial->port[i];
-               if (!port)
-                       continue;
-               portdata = usb_get_serial_port_data(port);
-               if (!portdata)
-                       continue;
-               kfree(portdata);
+       portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
+       if (!portdata)
+               return -ENOMEM;
+
+       spin_lock_init(&portdata->lock);
+       init_usb_anchor(&portdata->active);
+       init_usb_anchor(&portdata->delayed);
+
+       /* Assume low memory requirements */
+       portdata->num_out_urbs = N_OUT_URB;
+       portdata->num_in_urbs  = N_IN_URB;
+
+       /* Determine actual memory requirements */
+       if (serial->num_ports == 1) {
+               /* Get interface number for composite device */
+               ifnum = sierra_calc_interface(serial);
+               himemoryp = &typeB_interface_list;
+       } else {
+               /* This is really the usb-serial port number of the interface
+                * rather than the interface number.
+                */
+               ifnum = port->number - serial->minor;
+               himemoryp = &typeA_interface_list;
        }
+
+       if (is_himemory(ifnum, himemoryp)) {
+               portdata->num_out_urbs = N_OUT_URB_HM;
+               portdata->num_in_urbs  = N_IN_URB_HM;
+       }
+
+       dev_dbg(&port->dev,
+                       "Memory usage (urbs) interface #%d, in=%d, out=%d\n",
+                       ifnum, portdata->num_in_urbs, portdata->num_out_urbs);
+
+       usb_set_serial_port_data(port, portdata);
+
+       return 0;
+}
+
+static int sierra_port_remove(struct usb_serial_port *port)
+{
+       struct sierra_port_private *portdata;
+
+       portdata = usb_get_serial_port_data(port);
+       kfree(portdata);
+
+       return 0;
 }
 
 #ifdef CONFIG_PM
@@ -1062,6 +1063,8 @@ static struct usb_serial_driver sierra_device = {
        .tiocmset          = sierra_tiocmset,
        .attach            = sierra_startup,
        .release           = sierra_release,
+       .port_probe        = sierra_port_probe,
+       .port_remove       = sierra_port_remove,
        .suspend           = sierra_suspend,
        .resume            = sierra_resume,
        .read_int_callback = sierra_instat_callback,
index 9716efe..769c137 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 015810b..868d1e6 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)
 {
@@ -442,21 +435,33 @@ 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 6f49392..f2530d2 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 1f034d2..684739b 100644 (file)
@@ -8,7 +8,7 @@
 extern void usb_wwan_dtr_rts(struct usb_serial_port *port, int on);
 extern int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port);
 extern void usb_wwan_close(struct usb_serial_port *port);
-extern int usb_wwan_startup(struct usb_serial *serial);
+extern int usb_wwan_port_probe(struct usb_serial_port *port);
 extern int usb_wwan_port_remove(struct usb_serial_port *port);
 extern int usb_wwan_write_room(struct tty_struct *tty);
 extern void usb_wwan_set_termios(struct tty_struct *tty,
index e42aa39..a3e9c09 100644 (file)
@@ -447,15 +447,14 @@ void usb_wwan_close(struct usb_serial_port *port)
 EXPORT_SYMBOL(usb_wwan_close);
 
 /* Helper functions used by usb_wwan_setup_urbs */
-static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint,
+static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
+                                     int endpoint,
                                      int dir, void *ctx, char *buf, int len,
                                      void (*callback) (struct urb *))
 {
+       struct usb_serial *serial = port->serial;
        struct urb *urb;
 
-       if (endpoint == -1)
-               return NULL;    /* endpoint not needed */
-
        urb = usb_alloc_urb(0, GFP_KERNEL);     /* No ISO */
        if (urb == NULL) {
                dev_dbg(&serial->interface->dev,
@@ -472,101 +471,78 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint,
        return urb;
 }
 
-/* Setup urbs */
-static void usb_wwan_setup_urbs(struct usb_serial *serial)
+int usb_wwan_port_probe(struct usb_serial_port *port)
 {
-       int i, j;
-       struct usb_serial_port *port;
        struct usb_wwan_port_private *portdata;
+       struct urb *urb;
+       u8 *buffer;
+       int err;
+       int i;
 
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-               portdata = usb_get_serial_port_data(port);
+       portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
+       if (!portdata)
+               return -ENOMEM;
 
-               /* Do indat endpoints first */
-               for (j = 0; j < N_IN_URB; ++j) {
-                       portdata->in_urbs[j] = usb_wwan_setup_urb(serial,
-                                                                 port->
-                                                                 bulk_in_endpointAddress,
-                                                                 USB_DIR_IN,
-                                                                 port,
-                                                                 portdata->
-                                                                 in_buffer[j],
-                                                                 IN_BUFLEN,
-                                                                 usb_wwan_indat_callback);
-               }
+       init_usb_anchor(&portdata->delayed);
 
-               /* outdat endpoints */
-               for (j = 0; j < N_OUT_URB; ++j) {
-                       portdata->out_urbs[j] = usb_wwan_setup_urb(serial,
-                                                                  port->
-                                                                  bulk_out_endpointAddress,
-                                                                  USB_DIR_OUT,
-                                                                  port,
-                                                                  portdata->
-                                                                  out_buffer
-                                                                  [j],
-                                                                  OUT_BUFLEN,
-                                                                  usb_wwan_outdat_callback);
-               }
-       }
-}
+       for (i = 0; i < N_IN_URB; i++) {
+               if (!port->bulk_in_size)
+                       break;
 
-int usb_wwan_startup(struct usb_serial *serial)
-{
-       int i, j, err;
-       struct usb_serial_port *port;
-       struct usb_wwan_port_private *portdata;
-       u8 *buffer;
+               buffer = (u8 *)__get_free_page(GFP_KERNEL);
+               if (!buffer)
+                       goto bail_out_error;
+               portdata->in_buffer[i] = buffer;
 
-       /* Now setup per port private data */
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-               portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
-               if (!portdata) {
-                       dev_dbg(&port->dev, "%s: kmalloc for usb_wwan_port_private (%d) failed!.\n",
-                               __func__, i);
-                       return 1;
-               }
-               init_usb_anchor(&portdata->delayed);
+               urb = usb_wwan_setup_urb(port, port->bulk_in_endpointAddress,
+                                               USB_DIR_IN, port,
+                                               buffer, IN_BUFLEN,
+                                               usb_wwan_indat_callback);
+               portdata->in_urbs[i] = urb;
+       }
 
-               for (j = 0; j < N_IN_URB; j++) {
-                       buffer = (u8 *) __get_free_page(GFP_KERNEL);
-                       if (!buffer)
-                               goto bail_out_error;
-                       portdata->in_buffer[j] = buffer;
-               }
+       for (i = 0; i < N_OUT_URB; i++) {
+               if (!port->bulk_out_size)
+                       break;
 
-               for (j = 0; j < N_OUT_URB; j++) {
-                       buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
-                       if (!buffer)
-                               goto bail_out_error2;
-                       portdata->out_buffer[j] = buffer;
-               }
+               buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
+               if (!buffer)
+                       goto bail_out_error2;
+               portdata->out_buffer[i] = buffer;
 
-               usb_set_serial_port_data(port, portdata);
+               urb = usb_wwan_setup_urb(port, port->bulk_out_endpointAddress,
+                                               USB_DIR_OUT, port,
+                                               buffer, OUT_BUFLEN,
+                                               usb_wwan_outdat_callback);
+               portdata->out_urbs[i] = urb;
+       }
 
-               if (!port->interrupt_in_urb)
-                       continue;
+       usb_set_serial_port_data(port, portdata);
+
+       if (port->interrupt_in_urb) {
                err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
                if (err)
                        dev_dbg(&port->dev, "%s: submit irq_in urb failed %d\n",
                                __func__, err);
        }
-       usb_wwan_setup_urbs(serial);
+
        return 0;
 
 bail_out_error2:
-       for (j = 0; j < N_OUT_URB; j++)
-               kfree(portdata->out_buffer[j]);
+       for (i = 0; i < N_OUT_URB; i++) {
+               usb_free_urb(portdata->out_urbs[i]);
+               kfree(portdata->out_buffer[i]);
+       }
 bail_out_error:
-       for (j = 0; j < N_IN_URB; j++)
-               if (portdata->in_buffer[j])
-                       free_page((unsigned long)portdata->in_buffer[j]);
+       for (i = 0; i < N_IN_URB; i++) {
+               usb_free_urb(portdata->in_urbs[i]);
+               free_page((unsigned long)portdata->in_buffer[i]);
+       }
        kfree(portdata);
-       return 1;
+
+       return -ENOMEM;
 }
-EXPORT_SYMBOL(usb_wwan_startup);
+EXPORT_SYMBOL_GPL(usb_wwan_port_probe);
 
 int usb_wwan_port_remove(struct usb_serial_port *port)
 {
index 346c7ef..b9fca35 100644 (file)
@@ -83,6 +83,8 @@ static int  whiteheat_firmware_attach(struct usb_serial *serial);
 /* function prototypes for the Connect Tech WhiteHEAT serial converter */
 static int  whiteheat_attach(struct usb_serial *serial);
 static void whiteheat_release(struct usb_serial *serial);
+static int  whiteheat_port_probe(struct usb_serial_port *port);
+static int  whiteheat_port_remove(struct usb_serial_port *port);
 static int  whiteheat_open(struct tty_struct *tty,
                        struct usb_serial_port *port);
 static void whiteheat_close(struct usb_serial_port *port);
@@ -117,6 +119,8 @@ static struct usb_serial_driver whiteheat_device = {
        .num_ports =            4,
        .attach =               whiteheat_attach,
        .release =              whiteheat_release,
+       .port_probe =           whiteheat_port_probe,
+       .port_remove =          whiteheat_port_remove,
        .open =                 whiteheat_open,
        .close =                whiteheat_close,
        .ioctl =                whiteheat_ioctl,
@@ -218,15 +222,12 @@ static int whiteheat_attach(struct usb_serial *serial)
 {
        struct usb_serial_port *command_port;
        struct whiteheat_command_private *command_info;
-       struct usb_serial_port *port;
-       struct whiteheat_private *info;
        struct whiteheat_hw_info *hw_info;
        int pipe;
        int ret;
        int alen;
        __u8 *command;
        __u8 *result;
-       int i;
 
        command_port = serial->port[COMMAND_PORT];
 
@@ -285,22 +286,6 @@ static int whiteheat_attach(struct usb_serial *serial)
                 serial->type->description,
                 hw_info->sw_major_rev, hw_info->sw_minor_rev);
 
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-
-               info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
-               if (info == NULL) {
-                       dev_err(&port->dev,
-                               "%s: Out of memory for port structures\n",
-                               serial->type->description);
-                       goto no_private;
-               }
-
-               info->mcr = 0;
-
-               usb_set_serial_port_data(port, info);
-       }
-
        command_info = kmalloc(sizeof(struct whiteheat_command_private),
                                                                GFP_KERNEL);
        if (command_info == NULL) {
@@ -333,16 +318,10 @@ no_firmware:
                "%s: please contact support@connecttech.com\n",
                serial->type->description);
        kfree(result);
+       kfree(command);
        return -ENODEV;
 
 no_command_private:
-       for (i = serial->num_ports - 1; i >= 0; i--) {
-               port = serial->port[i];
-               info = usb_get_serial_port_data(port);
-               kfree(info);
-no_private:
-               ;
-       }
        kfree(result);
 no_result_buffer:
        kfree(command);
@@ -350,21 +329,36 @@ no_command_buffer:
        return -ENOMEM;
 }
 
-
 static void whiteheat_release(struct usb_serial *serial)
 {
        struct usb_serial_port *command_port;
-       struct whiteheat_private *info;
-       int i;
 
        /* free up our private data for our command port */
        command_port = serial->port[COMMAND_PORT];
        kfree(usb_get_serial_port_data(command_port));
+}
 
-       for (i = 0; i < serial->num_ports; i++) {
-               info = usb_get_serial_port_data(serial->port[i]);
-               kfree(info);
-       }
+static int whiteheat_port_probe(struct usb_serial_port *port)
+{
+       struct whiteheat_private *info;
+
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       usb_set_serial_port_data(port, info);
+
+       return 0;
+}
+
+static int whiteheat_port_remove(struct usb_serial_port *port)
+{
+       struct whiteheat_private *info;
+
+       info = usb_get_serial_port_data(port);
+       kfree(info);
+
+       return 0;
 }
 
 static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port)
index a3d5436..92f35ab 100644 (file)
@@ -186,6 +186,12 @@ static int slave_configure(struct scsi_device *sdev)
                /* Some devices don't handle VPD pages correctly */
                sdev->skip_vpd_pages = 1;
 
+               /* Do not attempt to use REPORT SUPPORTED OPERATION CODES */
+               sdev->no_report_opcodes = 1;
+
+               /* Do not attempt to use WRITE SAME */
+               sdev->no_write_same = 1;
+
                /* Some disks return the total number of blocks in response
                 * to READ CAPACITY rather than the highest block number.
                 * If this device makes that mistake, tell the sd driver. */
index 779cd95..d305a5a 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 072cbba..7f93f34 100644 (file)
@@ -379,7 +379,8 @@ static void handle_rx(struct vhost_net *net)
                .hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE
        };
        size_t total_len = 0;
-       int err, headcount, mergeable;
+       int err, mergeable;
+       s16 headcount;
        size_t vhost_hlen, sock_hlen;
        size_t vhost_len, sock_len;
        /* TODO: check that we are running from vhost_worker? */
index 99ac2cb..dedaf81 100644 (file)
@@ -1076,7 +1076,7 @@ static int translate_desc(struct vhost_dev *dev, u64 addr, u32 len,
                }
                _iov = iov + ret;
                size = reg->memory_size - addr + reg->guest_phys_addr;
-               _iov->iov_len = min((u64)len, size);
+               _iov->iov_len = min((u64)len - s, size);
                _iov->iov_base = (void __user *)(unsigned long)
                        (reg->userspace_addr + addr - reg->guest_phys_addr);
                s += size;
index c101697..765a945 100644 (file)
@@ -60,7 +60,8 @@ config LCD_LTV350QV
          The LTV350QV panel is present on all ATSTK1000 boards.
 
 config LCD_ILI9320
-       tristate
+       tristate "ILI Technology ILI9320 controller support"
+       depends on SPI
        help
          If you have a panel based on the ILI9320 controller chip
          then say y to include a power driver for it.
index c6915c6..585949b 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 d64ac38..bee9284 100644 (file)
@@ -365,11 +365,20 @@ struct platform_device *dsi_get_dsidev_from_id(int module)
        struct omap_dss_output *out;
        enum omap_dss_output_id id;
 
-       id = module == 0 ? OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
+       switch (module) {
+       case 0:
+               id = OMAP_DSS_OUTPUT_DSI1;
+               break;
+       case 1:
+               id = OMAP_DSS_OUTPUT_DSI2;
+               break;
+       default:
+               return NULL;
+       }
 
        out = omap_dss_get_output(id);
 
-       return out->pdev;
+       return out ? out->pdev : NULL;
 }
 
 static inline void dsi_write_reg(struct platform_device *dsidev,
index 2ab1c3e..5f6eea8 100644 (file)
@@ -697,11 +697,15 @@ static int dss_get_clocks(void)
 
        dss.dss_clk = clk;
 
-       clk = clk_get(NULL, dss.feat->clk_name);
-       if (IS_ERR(clk)) {
-               DSSERR("Failed to get %s\n", dss.feat->clk_name);
-               r = PTR_ERR(clk);
-               goto err;
+       if (dss.feat->clk_name) {
+               clk = clk_get(NULL, dss.feat->clk_name);
+               if (IS_ERR(clk)) {
+                       DSSERR("Failed to get %s\n", dss.feat->clk_name);
+                       r = PTR_ERR(clk);
+                       goto err;
+               }
+       } else {
+               clk = NULL;
        }
 
        dss.dpll4_m4_ck = clk;
@@ -805,10 +809,10 @@ static int __init dss_init_features(struct device *dev)
 
        if (cpu_is_omap24xx())
                src = &omap24xx_dss_feats;
-       else if (cpu_is_omap34xx())
-               src = &omap34xx_dss_feats;
        else if (cpu_is_omap3630())
                src = &omap3630_dss_feats;
+       else if (cpu_is_omap34xx())
+               src = &omap34xx_dss_feats;
        else if (cpu_is_omap44xx())
                src = &omap44xx_dss_feats;
        else if (soc_is_omap54xx())
index a48a7dd..8c9b8b3 100644 (file)
@@ -644,8 +644,10 @@ static void hdmi_dump_regs(struct seq_file *s)
 {
        mutex_lock(&hdmi.lock);
 
-       if (hdmi_runtime_get())
+       if (hdmi_runtime_get()) {
+               mutex_unlock(&hdmi.lock);
                return;
+       }
 
        hdmi.ip_data.ops->dump_wrapper(&hdmi.ip_data, s);
        hdmi.ip_data.ops->dump_pll(&hdmi.ip_data, s);
index 606b89f..d630b26 100644 (file)
@@ -787,7 +787,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
 
        case OMAPFB_WAITFORVSYNC:
                DBG("ioctl WAITFORVSYNC\n");
-               if (!display && !display->output && !display->output->manager) {
+               if (!display || !display->output || !display->output->manager) {
                        r = -EINVAL;
                        break;
                }
index b7f5173..917bb56 100644 (file)
@@ -641,7 +641,6 @@ static void xenfb_backend_changed(struct xenbus_device *dev,
        case XenbusStateReconfiguring:
        case XenbusStateReconfigured:
        case XenbusStateUnknown:
-       case XenbusStateClosed:
                break;
 
        case XenbusStateInitWait:
@@ -670,6 +669,10 @@ InitWait:
                info->feature_resize = val;
                break;
 
+       case XenbusStateClosed:
+               if (dev->state == XenbusStateClosed)
+                       break;
+               /* Missed the backend's CLOSING state -- fallthrough */
        case XenbusStateClosing:
                xenbus_frontend_closed(dev);
                break;
index 1e8659c..809b0de 100644 (file)
@@ -225,8 +225,10 @@ EXPORT_SYMBOL_GPL(register_virtio_device);
 
 void unregister_virtio_device(struct virtio_device *dev)
 {
+       int index = dev->index; /* save for after device release */
+
        device_unregister(&dev->dev);
-       ida_simple_remove(&virtio_index_ida, dev->index);
+       ida_simple_remove(&virtio_index_ida, index);
 }
 EXPORT_SYMBOL_GPL(unregister_virtio_device);
 
index d4dffcd..126d8ce 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 0e86370..7435470 100644 (file)
@@ -2,6 +2,7 @@ ifneq ($(CONFIG_ARM),y)
 obj-y  += manage.o balloon.o
 obj-$(CONFIG_HOTPLUG_CPU)              += cpu_hotplug.o
 endif
+obj-$(CONFIG_X86)                      += fallback.o
 obj-y  += grant-table.o features.o events.o
 obj-y  += xenbus/
 
index 31ab82f..d6886d9 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 42569c7..f3ccc80 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 59e10a1..0be4df3 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)
 {
@@ -1391,10 +1395,10 @@ void xen_evtchn_do_upcall(struct pt_regs *regs)
 {
        struct pt_regs *old_regs = set_irq_regs(regs);
 
+       irq_enter();
 #ifdef CONFIG_X86
        exit_idle();
 #endif
-       irq_enter();
 
        __xen_evtchn_do_upcall();
 
diff --git a/drivers/xen/fallback.c b/drivers/xen/fallback.c
new file mode 100644 (file)
index 0000000..0ef7c4d
--- /dev/null
@@ -0,0 +1,80 @@
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/bug.h>
+#include <linux/export.h>
+#include <asm/hypervisor.h>
+#include <asm/xen/hypercall.h>
+
+int xen_event_channel_op_compat(int cmd, void *arg)
+{
+       struct evtchn_op op;
+       int rc;
+
+       op.cmd = cmd;
+       memcpy(&op.u, arg, sizeof(op.u));
+       rc = _hypercall1(int, event_channel_op_compat, &op);
+
+       switch (cmd) {
+       case EVTCHNOP_close:
+       case EVTCHNOP_send:
+       case EVTCHNOP_bind_vcpu:
+       case EVTCHNOP_unmask:
+               /* no output */
+               break;
+
+#define COPY_BACK(eop) \
+       case EVTCHNOP_##eop: \
+               memcpy(arg, &op.u.eop, sizeof(op.u.eop)); \
+               break
+
+       COPY_BACK(bind_interdomain);
+       COPY_BACK(bind_virq);
+       COPY_BACK(bind_pirq);
+       COPY_BACK(status);
+       COPY_BACK(alloc_unbound);
+       COPY_BACK(bind_ipi);
+#undef COPY_BACK
+
+       default:
+               WARN_ON(rc != -ENOSYS);
+               break;
+       }
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL(xen_event_channel_op_compat);
+
+int HYPERVISOR_physdev_op_compat(int cmd, void *arg)
+{
+       struct physdev_op op;
+       int rc;
+
+       op.cmd = cmd;
+       memcpy(&op.u, arg, sizeof(op.u));
+       rc = _hypercall1(int, physdev_op_compat, &op);
+
+       switch (cmd) {
+       case PHYSDEVOP_IRQ_UNMASK_NOTIFY:
+       case PHYSDEVOP_set_iopl:
+       case PHYSDEVOP_set_iobitmap:
+       case PHYSDEVOP_apic_write:
+               /* no output */
+               break;
+
+#define COPY_BACK(pop, fld) \
+       case PHYSDEVOP_##pop: \
+               memcpy(arg, &op.u.fld, sizeof(op.u.fld)); \
+               break
+
+       COPY_BACK(irq_status_query, irq_status_query);
+       COPY_BACK(apic_read, apic_op);
+       COPY_BACK(ASSIGN_VECTOR, irq_op);
+#undef COPY_BACK
+
+       default:
+               WARN_ON(rc != -ENOSYS);
+               break;
+       }
+
+       return rc;
+}
index 610bfc6..2e22df2 100644 (file)
@@ -105,6 +105,21 @@ static void gntdev_print_maps(struct gntdev_priv *priv,
 #endif
 }
 
+static void gntdev_free_map(struct grant_map *map)
+{
+       if (map == NULL)
+               return;
+
+       if (map->pages)
+               free_xenballooned_pages(map->count, map->pages);
+       kfree(map->pages);
+       kfree(map->grants);
+       kfree(map->map_ops);
+       kfree(map->unmap_ops);
+       kfree(map->kmap_ops);
+       kfree(map);
+}
+
 static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
 {
        struct grant_map *add;
@@ -142,12 +157,7 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
        return add;
 
 err:
-       kfree(add->pages);
-       kfree(add->grants);
-       kfree(add->map_ops);
-       kfree(add->unmap_ops);
-       kfree(add->kmap_ops);
-       kfree(add);
+       gntdev_free_map(add);
        return NULL;
 }
 
@@ -198,17 +208,9 @@ static void gntdev_put_map(struct grant_map *map)
                evtchn_put(map->notify.event);
        }
 
-       if (map->pages) {
-               if (!use_ptemod)
-                       unmap_grant_pages(map, 0, map->count);
-
-               free_xenballooned_pages(map->count, map->pages);
-       }
-       kfree(map->pages);
-       kfree(map->grants);
-       kfree(map->map_ops);
-       kfree(map->unmap_ops);
-       kfree(map);
+       if (map->pages && !use_ptemod)
+               unmap_grant_pages(map, 0, map->count);
+       gntdev_free_map(map);
 }
 
 /* ------------------------------------------------------------------ */
index b2b0a37..b91f14e 100644 (file)
@@ -84,7 +84,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.
@@ -960,7 +960,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 +977,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 +1029,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 8adb9cc..71f5c45 100644 (file)
@@ -361,13 +361,13 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
        down_write(&mm->mmap_sem);
 
        vma = find_vma(mm, m.addr);
-       ret = -EINVAL;
        if (!vma ||
            vma->vm_ops != &privcmd_vm_ops ||
            (m.addr != vma->vm_start) ||
            ((m.addr + (nr_pages << PAGE_SHIFT)) != vma->vm_end) ||
            !privcmd_enforce_singleshot_mapping(vma)) {
                up_write(&mm->mmap_sem);
+               ret = -EINVAL;
                goto out;
        }
 
@@ -383,12 +383,16 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
 
        up_write(&mm->mmap_sem);
 
-       if (state.global_error && (version == 1)) {
-               /* Write back errors in second pass. */
-               state.user_mfn = (xen_pfn_t *)m.arr;
-               state.err      = err_array;
-               ret = traverse_pages(m.num, sizeof(xen_pfn_t),
-                                    &pagelist, mmap_return_errors_v1, &state);
+       if (version == 1) {
+               if (state.global_error) {
+                       /* Write back errors in second pass. */
+                       state.user_mfn = (xen_pfn_t *)m.arr;
+                       state.err      = err_array;
+                       ret = traverse_pages(m.num, sizeof(xen_pfn_t),
+                                            &pagelist, mmap_return_errors_v1, &state);
+               } else
+                       ret = 0;
+
        } else if (version == 2) {
                ret = __copy_to_user(m.err, err_array, m.num * sizeof(int));
                if (ret)
index 5e5ad7e..96453f8 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 46d140b..0f478ac 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 89f7625..ac72702 100644 (file)
@@ -458,7 +458,7 @@ static ssize_t xenbus_file_write(struct file *filp,
                goto out;
 
        /* Can't write a xenbus message larger we can buffer */
-       if ((len + u->len) > sizeof(u->u.buffer)) {
+       if (len > sizeof(u->u.buffer) - u->len) {
                /* On error, dump existing buffer */
                u->len = 0;
                rc = -EINVAL;
index 48220e1..acedeab 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 9298c65..b96fc6c 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -75,6 +75,7 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size)
        unsigned int sz = sizeof(struct bio) + extra_size;
        struct kmem_cache *slab = NULL;
        struct bio_slab *bslab, *new_bio_slabs;
+       unsigned int new_bio_slab_max;
        unsigned int i, entry = -1;
 
        mutex_lock(&bio_slab_lock);
@@ -97,12 +98,13 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size)
                goto out_unlock;
 
        if (bio_slab_nr == bio_slab_max && entry == -1) {
-               bio_slab_max <<= 1;
+               new_bio_slab_max = bio_slab_max << 1;
                new_bio_slabs = krealloc(bio_slabs,
-                                        bio_slab_max * sizeof(struct bio_slab),
+                                        new_bio_slab_max * sizeof(struct bio_slab),
                                         GFP_KERNEL);
                if (!new_bio_slabs)
                        goto out_unlock;
+               bio_slab_max = new_bio_slab_max;
                bio_slabs = new_bio_slabs;
        }
        if (entry == -1)
index b3c1d3d..ab3a456 100644 (file)
@@ -70,19 +70,6 @@ static void bdev_inode_switch_bdi(struct inode *inode,
        spin_unlock(&dst->wb.list_lock);
 }
 
-sector_t blkdev_max_block(struct block_device *bdev)
-{
-       sector_t retval = ~((sector_t)0);
-       loff_t sz = i_size_read(bdev->bd_inode);
-
-       if (sz) {
-               unsigned int size = block_size(bdev);
-               unsigned int sizebits = blksize_bits(size);
-               retval = (sz >> sizebits);
-       }
-       return retval;
-}
-
 /* Kill _all_ buffers and pagecache , dirty or not.. */
 void kill_bdev(struct block_device *bdev)
 {
@@ -116,8 +103,6 @@ EXPORT_SYMBOL(invalidate_bdev);
 
 int set_blocksize(struct block_device *bdev, int size)
 {
-       struct address_space *mapping;
-
        /* Size must be a power of two, and between 512 and PAGE_SIZE */
        if (size > PAGE_SIZE || size < 512 || !is_power_of_2(size))
                return -EINVAL;
@@ -126,19 +111,6 @@ int set_blocksize(struct block_device *bdev, int size)
        if (size < bdev_logical_block_size(bdev))
                return -EINVAL;
 
-       /* Prevent starting I/O or mapping the device */
-       percpu_down_write(&bdev->bd_block_size_semaphore);
-
-       /* Check that the block device is not memory mapped */
-       mapping = bdev->bd_inode->i_mapping;
-       mutex_lock(&mapping->i_mmap_mutex);
-       if (mapping_mapped(mapping)) {
-               mutex_unlock(&mapping->i_mmap_mutex);
-               percpu_up_write(&bdev->bd_block_size_semaphore);
-               return -EBUSY;
-       }
-       mutex_unlock(&mapping->i_mmap_mutex);
-
        /* Don't change the size if it is same as current */
        if (bdev->bd_block_size != size) {
                sync_blockdev(bdev);
@@ -146,9 +118,6 @@ int set_blocksize(struct block_device *bdev, int size)
                bdev->bd_inode->i_blkbits = blksize_bits(size);
                kill_bdev(bdev);
        }
-
-       percpu_up_write(&bdev->bd_block_size_semaphore);
-
        return 0;
 }
 
@@ -181,52 +150,12 @@ static int
 blkdev_get_block(struct inode *inode, sector_t iblock,
                struct buffer_head *bh, int create)
 {
-       if (iblock >= blkdev_max_block(I_BDEV(inode))) {
-               if (create)
-                       return -EIO;
-
-               /*
-                * for reads, we're just trying to fill a partial page.
-                * return a hole, they will have to call get_block again
-                * before they can fill it, and they will get -EIO at that
-                * time
-                */
-               return 0;
-       }
        bh->b_bdev = I_BDEV(inode);
        bh->b_blocknr = iblock;
        set_buffer_mapped(bh);
        return 0;
 }
 
-static int
-blkdev_get_blocks(struct inode *inode, sector_t iblock,
-               struct buffer_head *bh, int create)
-{
-       sector_t end_block = blkdev_max_block(I_BDEV(inode));
-       unsigned long max_blocks = bh->b_size >> inode->i_blkbits;
-
-       if ((iblock + max_blocks) > end_block) {
-               max_blocks = end_block - iblock;
-               if ((long)max_blocks <= 0) {
-                       if (create)
-                               return -EIO;    /* write fully beyond EOF */
-                       /*
-                        * It is a read which is fully beyond EOF.  We return
-                        * a !buffer_mapped buffer
-                        */
-                       max_blocks = 0;
-               }
-       }
-
-       bh->b_bdev = I_BDEV(inode);
-       bh->b_blocknr = iblock;
-       bh->b_size = max_blocks << inode->i_blkbits;
-       if (max_blocks)
-               set_buffer_mapped(bh);
-       return 0;
-}
-
 static ssize_t
 blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
                        loff_t offset, unsigned long nr_segs)
@@ -235,7 +164,7 @@ blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
        struct inode *inode = file->f_mapping->host;
 
        return __blockdev_direct_IO(rw, iocb, inode, I_BDEV(inode), iov, offset,
-                                   nr_segs, blkdev_get_blocks, NULL, NULL, 0);
+                                   nr_segs, blkdev_get_block, NULL, NULL, 0);
 }
 
 int __sync_blockdev(struct block_device *bdev, int wait)
@@ -459,12 +388,6 @@ static struct inode *bdev_alloc_inode(struct super_block *sb)
        struct bdev_inode *ei = kmem_cache_alloc(bdev_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
-
-       if (unlikely(percpu_init_rwsem(&ei->bdev.bd_block_size_semaphore))) {
-               kmem_cache_free(bdev_cachep, ei);
-               return NULL;
-       }
-
        return &ei->vfs_inode;
 }
 
@@ -473,8 +396,6 @@ static void bdev_i_callback(struct rcu_head *head)
        struct inode *inode = container_of(head, struct inode, i_rcu);
        struct bdev_inode *bdi = BDEV_I(inode);
 
-       percpu_free_rwsem(&bdi->bdev.bd_block_size_semaphore);
-
        kmem_cache_free(bdev_cachep, bdi);
 }
 
@@ -1593,22 +1514,6 @@ static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg)
        return blkdev_ioctl(bdev, mode, cmd, arg);
 }
 
-ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov,
-                       unsigned long nr_segs, loff_t pos)
-{
-       ssize_t ret;
-       struct block_device *bdev = I_BDEV(iocb->ki_filp->f_mapping->host);
-
-       percpu_down_read(&bdev->bd_block_size_semaphore);
-
-       ret = generic_file_aio_read(iocb, iov, nr_segs, pos);
-
-       percpu_up_read(&bdev->bd_block_size_semaphore);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(blkdev_aio_read);
-
 /*
  * Write data to the block device.  Only intended for the block device itself
  * and the raw driver which basically is a fake block device.
@@ -1620,16 +1525,12 @@ ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov,
                         unsigned long nr_segs, loff_t pos)
 {
        struct file *file = iocb->ki_filp;
-       struct block_device *bdev = I_BDEV(file->f_mapping->host);
        struct blk_plug plug;
        ssize_t ret;
 
        BUG_ON(iocb->ki_pos != pos);
 
        blk_start_plug(&plug);
-
-       percpu_down_read(&bdev->bd_block_size_semaphore);
-
        ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos);
        if (ret > 0 || ret == -EIOCBQUEUED) {
                ssize_t err;
@@ -1638,27 +1539,25 @@ ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov,
                if (err < 0 && ret > 0)
                        ret = err;
        }
-
-       percpu_up_read(&bdev->bd_block_size_semaphore);
-
        blk_finish_plug(&plug);
-
        return ret;
 }
 EXPORT_SYMBOL_GPL(blkdev_aio_write);
 
-static int blkdev_mmap(struct file *file, struct vm_area_struct *vma)
+static ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov,
+                        unsigned long nr_segs, loff_t pos)
 {
-       int ret;
-       struct block_device *bdev = I_BDEV(file->f_mapping->host);
-
-       percpu_down_read(&bdev->bd_block_size_semaphore);
-
-       ret = generic_file_mmap(file, vma);
+       struct file *file = iocb->ki_filp;
+       struct inode *bd_inode = file->f_mapping->host;
+       loff_t size = i_size_read(bd_inode);
 
-       percpu_up_read(&bdev->bd_block_size_semaphore);
+       if (pos >= size)
+               return 0;
 
-       return ret;
+       size -= pos;
+       if (size < INT_MAX)
+               nr_segs = iov_shorten((struct iovec *)iov, nr_segs, size);
+       return generic_file_aio_read(iocb, iov, nr_segs, pos);
 }
 
 /*
@@ -1691,9 +1590,9 @@ const struct file_operations def_blk_fops = {
        .llseek         = block_llseek,
        .read           = do_sync_read,
        .write          = do_sync_write,
-       .aio_read       = blkdev_aio_read,
+       .aio_read       = blkdev_aio_read,
        .aio_write      = blkdev_aio_write,
-       .mmap           = blkdev_mmap,
+       .mmap           = generic_file_mmap,
        .fsync          = blkdev_fsync,
        .unlocked_ioctl = block_ioctl,
 #ifdef CONFIG_COMPAT
index f318793..208d8aa 100644 (file)
@@ -283,9 +283,7 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
                goto out;
        }
 
-       rcu_read_lock();
-       root_level = btrfs_header_level(root->node);
-       rcu_read_unlock();
+       root_level = btrfs_old_root_level(root, time_seq);
 
        if (root_level + 1 == level)
                goto out;
@@ -1177,16 +1175,15 @@ int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid,
        return ret;
 }
 
-static char *ref_to_path(struct btrfs_root *fs_root,
-                        struct btrfs_path *path,
-                        u32 name_len, unsigned long name_off,
-                        struct extent_buffer *eb_in, u64 parent,
-                        char *dest, u32 size)
+char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
+                       u32 name_len, unsigned long name_off,
+                       struct extent_buffer *eb_in, u64 parent,
+                       char *dest, u32 size)
 {
        int slot;
        u64 next_inum;
        int ret;
-       s64 bytes_left = size - 1;
+       s64 bytes_left = ((s64)size) - 1;
        struct extent_buffer *eb = eb_in;
        struct btrfs_key found_key;
        int leave_spinning = path->leave_spinning;
@@ -1266,10 +1263,10 @@ char *btrfs_iref_to_path(struct btrfs_root *fs_root,
                         struct extent_buffer *eb_in, u64 parent,
                         char *dest, u32 size)
 {
-       return ref_to_path(fs_root, path,
-                          btrfs_inode_ref_name_len(eb_in, iref),
-                          (unsigned long)(iref + 1),
-                          eb_in, parent, dest, size);
+       return btrfs_ref_to_path(fs_root, path,
+                                btrfs_inode_ref_name_len(eb_in, iref),
+                                (unsigned long)(iref + 1),
+                                eb_in, parent, dest, size);
 }
 
 /*
@@ -1715,9 +1712,8 @@ static int inode_to_path(u64 inum, u32 name_len, unsigned long name_off,
                                        ipath->fspath->bytes_left - s_ptr : 0;
 
        fspath_min = (char *)ipath->fspath->val + (i + 1) * s_ptr;
-       fspath = ref_to_path(ipath->fs_root, ipath->btrfs_path, name_len,
-                            name_off, eb, inum, fspath_min,
-                            bytes_left);
+       fspath = btrfs_ref_to_path(ipath->fs_root, ipath->btrfs_path, name_len,
+                                  name_off, eb, inum, fspath_min, bytes_left);
        if (IS_ERR(fspath))
                return PTR_ERR(fspath);
 
index e755330..d61feca 100644 (file)
@@ -62,6 +62,10 @@ int btrfs_find_all_roots(struct btrfs_trans_handle *trans,
 char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
                         struct btrfs_inode_ref *iref, struct extent_buffer *eb,
                         u64 parent, char *dest, u32 size);
+char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
+                       u32 name_len, unsigned long name_off,
+                       struct extent_buffer *eb_in, u64 parent,
+                       char *dest, u32 size);
 
 struct btrfs_data_container *init_data_container(u32 total_bytes);
 struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root,
index b334362..cdfb4c4 100644 (file)
@@ -596,6 +596,11 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info,
        if (tree_mod_dont_log(fs_info, eb))
                return 0;
 
+       /*
+        * When we override something during the move, we log these removals.
+        * This can only happen when we move towards the beginning of the
+        * buffer, i.e. dst_slot < src_slot.
+        */
        for (i = 0; i + dst_slot < src_slot && i < nr_items; i++) {
                ret = tree_mod_log_insert_key_locked(fs_info, eb, i + dst_slot,
                                              MOD_LOG_KEY_REMOVE_WHILE_MOVING);
@@ -647,8 +652,6 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info,
        if (tree_mod_dont_log(fs_info, NULL))
                return 0;
 
-       __tree_mod_log_free_eb(fs_info, old_root);
-
        ret = tree_mod_alloc(fs_info, flags, &tm);
        if (ret < 0)
                goto out;
@@ -926,12 +929,7 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
                        ret = btrfs_dec_ref(trans, root, buf, 1, 1);
                        BUG_ON(ret); /* -ENOMEM */
                }
-               /*
-                * don't log freeing in case we're freeing the root node, this
-                * is done by tree_mod_log_set_root_pointer later
-                */
-               if (buf != root->node && btrfs_header_level(buf) != 0)
-                       tree_mod_log_free_eb(root->fs_info, buf);
+               tree_mod_log_free_eb(root->fs_info, buf);
                clean_tree_block(trans, root, buf);
                *last_ref = 1;
        }
@@ -1225,6 +1223,8 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb,
        free_extent_buffer(eb);
 
        __tree_mod_log_rewind(eb_rewin, time_seq, tm);
+       WARN_ON(btrfs_header_nritems(eb_rewin) >
+               BTRFS_NODEPTRS_PER_BLOCK(fs_info->fs_root));
 
        return eb_rewin;
 }
@@ -1241,9 +1241,11 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
 {
        struct tree_mod_elem *tm;
        struct extent_buffer *eb;
+       struct extent_buffer *old;
        struct tree_mod_root *old_root = NULL;
        u64 old_generation = 0;
        u64 logical;
+       u32 blocksize;
 
        eb = btrfs_read_lock_root_node(root);
        tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq);
@@ -1259,14 +1261,32 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
        }
 
        tm = tree_mod_log_search(root->fs_info, logical, time_seq);
-       if (old_root)
+       if (old_root && tm && tm->op != MOD_LOG_KEY_REMOVE_WHILE_FREEING) {
+               btrfs_tree_read_unlock(root->node);
+               free_extent_buffer(root->node);
+               blocksize = btrfs_level_size(root, old_root->level);
+               old = read_tree_block(root, logical, blocksize, 0);
+               if (!old) {
+                       pr_warn("btrfs: failed to read tree block %llu from get_old_root\n",
+                               logical);
+                       WARN_ON(1);
+               } else {
+                       eb = btrfs_clone_extent_buffer(old);
+                       free_extent_buffer(old);
+               }
+       } else if (old_root) {
+               btrfs_tree_read_unlock(root->node);
+               free_extent_buffer(root->node);
                eb = alloc_dummy_extent_buffer(logical, root->nodesize);
-       else
+       } else {
                eb = btrfs_clone_extent_buffer(root->node);
-       btrfs_tree_read_unlock(root->node);
-       free_extent_buffer(root->node);
+               btrfs_tree_read_unlock(root->node);
+               free_extent_buffer(root->node);
+       }
+
        if (!eb)
                return NULL;
+       extent_buffer_get(eb);
        btrfs_tree_read_lock(eb);
        if (old_root) {
                btrfs_set_header_bytenr(eb, eb->start);
@@ -1279,11 +1299,28 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
                __tree_mod_log_rewind(eb, time_seq, tm);
        else
                WARN_ON(btrfs_header_level(eb) != 0);
-       extent_buffer_get(eb);
+       WARN_ON(btrfs_header_nritems(eb) > BTRFS_NODEPTRS_PER_BLOCK(root));
 
        return eb;
 }
 
+int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq)
+{
+       struct tree_mod_elem *tm;
+       int level;
+
+       tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq);
+       if (tm && tm->op == MOD_LOG_ROOT_REPLACE) {
+               level = tm->old_root.level;
+       } else {
+               rcu_read_lock();
+               level = btrfs_header_level(root->node);
+               rcu_read_unlock();
+       }
+
+       return level;
+}
+
 static inline int should_cow_block(struct btrfs_trans_handle *trans,
                                   struct btrfs_root *root,
                                   struct extent_buffer *buf)
@@ -1725,6 +1762,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
                        goto enospc;
                }
 
+               tree_mod_log_free_eb(root->fs_info, root->node);
                tree_mod_log_set_root_pointer(root, child);
                rcu_assign_pointer(root->node, child);
 
@@ -2970,8 +3008,10 @@ static int push_node_left(struct btrfs_trans_handle *trans,
                           push_items * sizeof(struct btrfs_key_ptr));
 
        if (push_items < src_nritems) {
-               tree_mod_log_eb_move(root->fs_info, src, 0, push_items,
-                                    src_nritems - push_items);
+               /*
+                * don't call tree_mod_log_eb_move here, key removal was already
+                * fully logged by tree_mod_log_eb_copy above.
+                */
                memmove_extent_buffer(src, btrfs_node_key_ptr_offset(0),
                                      btrfs_node_key_ptr_offset(push_items),
                                      (src_nritems - push_items) *
index 926c9ff..c72ead8 100644 (file)
@@ -3120,6 +3120,7 @@ static inline u64 btrfs_inc_tree_mod_seq(struct btrfs_fs_info *fs_info)
 {
        return atomic_inc_return(&fs_info->tree_mod_seq);
 }
+int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq);
 
 /* root-item.c */
 int btrfs_find_root_ref(struct btrfs_root *tree_root,
@@ -3338,6 +3339,8 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
 int btrfs_update_inode(struct btrfs_trans_handle *trans,
                              struct btrfs_root *root,
                              struct inode *inode);
+int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
+                               struct btrfs_root *root, struct inode *inode);
 int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode);
 int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode);
 int btrfs_orphan_cleanup(struct btrfs_root *root);
index 8036d3a..472873a 100644 (file)
@@ -4110,8 +4110,8 @@ struct extent_buffer *alloc_dummy_extent_buffer(u64 start, unsigned long len)
 
        return eb;
 err:
-       for (i--; i >= 0; i--)
-               __free_page(eb->pages[i]);
+       for (; i > 0; i--)
+               __free_page(eb->pages[i - 1]);
        __free_extent_buffer(eb);
        return NULL;
 }
index 85a1e50..95542a1 100644 (file)
@@ -94,8 +94,6 @@ static noinline int cow_file_range(struct inode *inode,
                                   struct page *locked_page,
                                   u64 start, u64 end, int *page_started,
                                   unsigned long *nr_written, int unlock);
-static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
-                               struct btrfs_root *root, struct inode *inode);
 
 static int btrfs_init_inode_security(struct btrfs_trans_handle *trans,
                                     struct inode *inode,  struct inode *dir,
@@ -2746,8 +2744,9 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans,
        return btrfs_update_inode_item(trans, root, inode);
 }
 
-static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
-                               struct btrfs_root *root, struct inode *inode)
+noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
+                                        struct btrfs_root *root,
+                                        struct inode *inode)
 {
        int ret;
 
index 6116880..8fcf9a5 100644 (file)
@@ -343,7 +343,8 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg)
                return -EOPNOTSUPP;
        if (copy_from_user(&range, arg, sizeof(range)))
                return -EFAULT;
-       if (range.start > total_bytes)
+       if (range.start > total_bytes ||
+           range.len < fs_info->sb->s_blocksize)
                return -EINVAL;
 
        range.len = min(range.len, total_bytes - range.start);
@@ -570,7 +571,8 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
                ret = btrfs_commit_transaction(trans,
                                               root->fs_info->extent_root);
        }
-       BUG_ON(ret);
+       if (ret)
+               goto fail;
 
        ret = pending_snapshot->error;
        if (ret)
index 5039686..fe9d02c 100644 (file)
@@ -790,8 +790,10 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans,
        }
 
        path = btrfs_alloc_path();
-       if (!path)
-               return -ENOMEM;
+       if (!path) {
+               ret = -ENOMEM;
+               goto out_free_root;
+       }
 
        key.objectid = 0;
        key.type = BTRFS_QGROUP_STATUS_KEY;
@@ -800,7 +802,7 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans,
        ret = btrfs_insert_empty_item(trans, quota_root, path, &key,
                                      sizeof(*ptr));
        if (ret)
-               goto out;
+               goto out_free_path;
 
        leaf = path->nodes[0];
        ptr = btrfs_item_ptr(leaf, path->slots[0],
@@ -818,8 +820,15 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans,
        fs_info->quota_root = quota_root;
        fs_info->pending_quota_state = 1;
        spin_unlock(&fs_info->qgroup_lock);
-out:
+out_free_path:
        btrfs_free_path(path);
+out_free_root:
+       if (ret) {
+               free_extent_buffer(quota_root->node);
+               free_extent_buffer(quota_root->commit_root);
+               kfree(quota_root);
+       }
+out:
        return ret;
 }
 
index c7beb54..e78b297 100644 (file)
@@ -745,31 +745,36 @@ typedef int (*iterate_inode_ref_t)(int num, u64 dir, int index,
                                   void *ctx);
 
 /*
- * Helper function to iterate the entries in ONE btrfs_inode_ref.
+ * Helper function to iterate the entries in ONE btrfs_inode_ref or
+ * btrfs_inode_extref.
  * The iterate callback may return a non zero value to stop iteration. This can
  * be a negative value for error codes or 1 to simply stop it.
  *
- * path must point to the INODE_REF when called.
+ * path must point to the INODE_REF or INODE_EXTREF when called.
  */
 static int iterate_inode_ref(struct send_ctx *sctx,
                             struct btrfs_root *root, struct btrfs_path *path,
                             struct btrfs_key *found_key, int resolve,
                             iterate_inode_ref_t iterate, void *ctx)
 {
-       struct extent_buffer *eb;
+       struct extent_buffer *eb = path->nodes[0];
        struct btrfs_item *item;
        struct btrfs_inode_ref *iref;
+       struct btrfs_inode_extref *extref;
        struct btrfs_path *tmp_path;
        struct fs_path *p;
-       u32 cur;
-       u32 len;
+       u32 cur = 0;
        u32 total;
-       int slot;
+       int slot = path->slots[0];
        u32 name_len;
        char *start;
        int ret = 0;
-       int num;
+       int num = 0;
        int index;
+       u64 dir;
+       unsigned long name_off;
+       unsigned long elem_size;
+       unsigned long ptr;
 
        p = fs_path_alloc_reversed(sctx);
        if (!p)
@@ -781,24 +786,40 @@ static int iterate_inode_ref(struct send_ctx *sctx,
                return -ENOMEM;
        }
 
-       eb = path->nodes[0];
-       slot = path->slots[0];
-       item = btrfs_item_nr(eb, slot);
-       iref = btrfs_item_ptr(eb, slot, struct btrfs_inode_ref);
-       cur = 0;
-       len = 0;
-       total = btrfs_item_size(eb, item);
 
-       num = 0;
+       if (found_key->type == BTRFS_INODE_REF_KEY) {
+               ptr = (unsigned long)btrfs_item_ptr(eb, slot,
+                                                   struct btrfs_inode_ref);
+               item = btrfs_item_nr(eb, slot);
+               total = btrfs_item_size(eb, item);
+               elem_size = sizeof(*iref);
+       } else {
+               ptr = btrfs_item_ptr_offset(eb, slot);
+               total = btrfs_item_size_nr(eb, slot);
+               elem_size = sizeof(*extref);
+       }
+
        while (cur < total) {
                fs_path_reset(p);
 
-               name_len = btrfs_inode_ref_name_len(eb, iref);
-               index = btrfs_inode_ref_index(eb, iref);
+               if (found_key->type == BTRFS_INODE_REF_KEY) {
+                       iref = (struct btrfs_inode_ref *)(ptr + cur);
+                       name_len = btrfs_inode_ref_name_len(eb, iref);
+                       name_off = (unsigned long)(iref + 1);
+                       index = btrfs_inode_ref_index(eb, iref);
+                       dir = found_key->offset;
+               } else {
+                       extref = (struct btrfs_inode_extref *)(ptr + cur);
+                       name_len = btrfs_inode_extref_name_len(eb, extref);
+                       name_off = (unsigned long)&extref->name;
+                       index = btrfs_inode_extref_index(eb, extref);
+                       dir = btrfs_inode_extref_parent(eb, extref);
+               }
+
                if (resolve) {
-                       start = btrfs_iref_to_path(root, tmp_path, iref, eb,
-                                               found_key->offset, p->buf,
-                                               p->buf_len);
+                       start = btrfs_ref_to_path(root, tmp_path, name_len,
+                                                 name_off, eb, dir,
+                                                 p->buf, p->buf_len);
                        if (IS_ERR(start)) {
                                ret = PTR_ERR(start);
                                goto out;
@@ -809,9 +830,10 @@ static int iterate_inode_ref(struct send_ctx *sctx,
                                                p->buf_len + p->buf - start);
                                if (ret < 0)
                                        goto out;
-                               start = btrfs_iref_to_path(root, tmp_path, iref,
-                                               eb, found_key->offset, p->buf,
-                                               p->buf_len);
+                               start = btrfs_ref_to_path(root, tmp_path,
+                                                         name_len, name_off,
+                                                         eb, dir,
+                                                         p->buf, p->buf_len);
                                if (IS_ERR(start)) {
                                        ret = PTR_ERR(start);
                                        goto out;
@@ -820,21 +842,16 @@ static int iterate_inode_ref(struct send_ctx *sctx,
                        }
                        p->start = start;
                } else {
-                       ret = fs_path_add_from_extent_buffer(p, eb,
-                                       (unsigned long)(iref + 1), name_len);
+                       ret = fs_path_add_from_extent_buffer(p, eb, name_off,
+                                                            name_len);
                        if (ret < 0)
                                goto out;
                }
 
-
-               len = sizeof(*iref) + name_len;
-               iref = (struct btrfs_inode_ref *)((char *)iref + len);
-               cur += len;
-
-               ret = iterate(num, found_key->offset, index, p, ctx);
+               cur += elem_size + name_len;
+               ret = iterate(num, dir, index, p, ctx);
                if (ret)
                        goto out;
-
                num++;
        }
 
@@ -998,7 +1015,8 @@ static int get_inode_path(struct send_ctx *sctx, struct btrfs_root *root,
        }
        btrfs_item_key_to_cpu(p->nodes[0], &found_key, p->slots[0]);
        if (found_key.objectid != ino ||
-               found_key.type != BTRFS_INODE_REF_KEY) {
+           (found_key.type != BTRFS_INODE_REF_KEY &&
+            found_key.type != BTRFS_INODE_EXTREF_KEY)) {
                ret = -ENOENT;
                goto out;
        }
@@ -1551,8 +1569,8 @@ static int get_first_ref(struct send_ctx *sctx,
        struct btrfs_key key;
        struct btrfs_key found_key;
        struct btrfs_path *path;
-       struct btrfs_inode_ref *iref;
        int len;
+       u64 parent_dir;
 
        path = alloc_path_for_send();
        if (!path)
@@ -1568,27 +1586,41 @@ static int get_first_ref(struct send_ctx *sctx,
        if (!ret)
                btrfs_item_key_to_cpu(path->nodes[0], &found_key,
                                path->slots[0]);
-       if (ret || found_key.objectid != key.objectid ||
-           found_key.type != key.type) {
+       if (ret || found_key.objectid != ino ||
+           (found_key.type != BTRFS_INODE_REF_KEY &&
+            found_key.type != BTRFS_INODE_EXTREF_KEY)) {
                ret = -ENOENT;
                goto out;
        }
 
-       iref = btrfs_item_ptr(path->nodes[0], path->slots[0],
-                       struct btrfs_inode_ref);
-       len = btrfs_inode_ref_name_len(path->nodes[0], iref);
-       ret = fs_path_add_from_extent_buffer(name, path->nodes[0],
-                       (unsigned long)(iref + 1), len);
+       if (key.type == BTRFS_INODE_REF_KEY) {
+               struct btrfs_inode_ref *iref;
+               iref = btrfs_item_ptr(path->nodes[0], path->slots[0],
+                                     struct btrfs_inode_ref);
+               len = btrfs_inode_ref_name_len(path->nodes[0], iref);
+               ret = fs_path_add_from_extent_buffer(name, path->nodes[0],
+                                                    (unsigned long)(iref + 1),
+                                                    len);
+               parent_dir = found_key.offset;
+       } else {
+               struct btrfs_inode_extref *extref;
+               extref = btrfs_item_ptr(path->nodes[0], path->slots[0],
+                                       struct btrfs_inode_extref);
+               len = btrfs_inode_extref_name_len(path->nodes[0], extref);
+               ret = fs_path_add_from_extent_buffer(name, path->nodes[0],
+                                       (unsigned long)&extref->name, len);
+               parent_dir = btrfs_inode_extref_parent(path->nodes[0], extref);
+       }
        if (ret < 0)
                goto out;
        btrfs_release_path(path);
 
-       ret = get_inode_info(root, found_key.offset, NULL, dir_gen, NULL, NULL,
+       ret = get_inode_info(root, parent_dir, NULL, dir_gen, NULL, NULL,
                        NULL, NULL);
        if (ret < 0)
                goto out;
 
-       *dir = found_key.offset;
+       *dir = parent_dir;
 
 out:
        btrfs_free_path(path);
@@ -2430,7 +2462,8 @@ verbose_printk("btrfs: send_create_inode %llu\n", ino);
                TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH_LINK, p);
        } else if (S_ISCHR(mode) || S_ISBLK(mode) ||
                   S_ISFIFO(mode) || S_ISSOCK(mode)) {
-               TLV_PUT_U64(sctx, BTRFS_SEND_A_RDEV, rdev);
+               TLV_PUT_U64(sctx, BTRFS_SEND_A_RDEV, new_encode_dev(rdev));
+               TLV_PUT_U64(sctx, BTRFS_SEND_A_MODE, mode);
        }
 
        ret = send_cmd(sctx);
@@ -3226,7 +3259,8 @@ static int process_all_refs(struct send_ctx *sctx,
                btrfs_item_key_to_cpu(eb, &found_key, slot);
 
                if (found_key.objectid != key.objectid ||
-                   found_key.type != key.type)
+                   (found_key.type != BTRFS_INODE_REF_KEY &&
+                    found_key.type != BTRFS_INODE_EXTREF_KEY))
                        break;
 
                ret = iterate_inode_ref(sctx, root, path, &found_key, 0, cb,
@@ -3987,7 +4021,7 @@ static int process_recorded_refs_if_needed(struct send_ctx *sctx, int at_end)
        if (sctx->cur_ino == 0)
                goto out;
        if (!at_end && sctx->cur_ino == sctx->cmp_key->objectid &&
-           sctx->cmp_key->type <= BTRFS_INODE_REF_KEY)
+           sctx->cmp_key->type <= BTRFS_INODE_EXTREF_KEY)
                goto out;
        if (list_empty(&sctx->new_refs) && list_empty(&sctx->deleted_refs))
                goto out;
@@ -4033,22 +4067,21 @@ static int finish_inode_if_needed(struct send_ctx *sctx, int at_end)
        if (ret < 0)
                goto out;
 
-       if (!S_ISLNK(sctx->cur_inode_mode)) {
-               if (!sctx->parent_root || sctx->cur_inode_new) {
+       if (!sctx->parent_root || sctx->cur_inode_new) {
+               need_chown = 1;
+               if (!S_ISLNK(sctx->cur_inode_mode))
                        need_chmod = 1;
-                       need_chown = 1;
-               } else {
-                       ret = get_inode_info(sctx->parent_root, sctx->cur_ino,
-                                       NULL, NULL, &right_mode, &right_uid,
-                                       &right_gid, NULL);
-                       if (ret < 0)
-                               goto out;
+       } else {
+               ret = get_inode_info(sctx->parent_root, sctx->cur_ino,
+                               NULL, NULL, &right_mode, &right_uid,
+                               &right_gid, NULL);
+               if (ret < 0)
+                       goto out;
 
-                       if (left_uid != right_uid || left_gid != right_gid)
-                               need_chown = 1;
-                       if (left_mode != right_mode)
-                               need_chmod = 1;
-               }
+               if (left_uid != right_uid || left_gid != right_gid)
+                       need_chown = 1;
+               if (!S_ISLNK(sctx->cur_inode_mode) && left_mode != right_mode)
+                       need_chmod = 1;
        }
 
        if (S_ISREG(sctx->cur_inode_mode)) {
@@ -4335,7 +4368,8 @@ static int changed_cb(struct btrfs_root *left_root,
 
        if (key->type == BTRFS_INODE_ITEM_KEY)
                ret = changed_inode(sctx, result);
-       else if (key->type == BTRFS_INODE_REF_KEY)
+       else if (key->type == BTRFS_INODE_REF_KEY ||
+                key->type == BTRFS_INODE_EXTREF_KEY)
                ret = changed_ref(sctx, result);
        else if (key->type == BTRFS_XATTR_ITEM_KEY)
                ret = changed_xattr(sctx, result);
index 77db875..04bbfb1 100644 (file)
@@ -1200,7 +1200,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        btrfs_i_size_write(parent_inode, parent_inode->i_size +
                                         dentry->d_name.len * 2);
        parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME;
-       ret = btrfs_update_inode(trans, parent_root, parent_inode);
+       ret = btrfs_update_inode_fallback(trans, parent_root, parent_inode);
        if (ret)
                btrfs_abort_transaction(trans, root, ret);
 fail:
index 029b903..0f5ebb7 100644 (file)
@@ -1819,6 +1819,13 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
                                    "Failed to relocate sys chunks after "
                                    "device initialization. This can be fixed "
                                    "using the \"btrfs balance\" command.");
+               trans = btrfs_attach_transaction(root);
+               if (IS_ERR(trans)) {
+                       if (PTR_ERR(trans) == -ENOENT)
+                               return 0;
+                       return PTR_ERR(trans);
+               }
+               ret = btrfs_commit_transaction(trans, root);
        }
 
        return ret;
index b5f0442..ec0aca8 100644 (file)
@@ -911,6 +911,18 @@ link_dev_buffers(struct page *page, struct buffer_head *head)
        attach_page_buffers(page, head);
 }
 
+static sector_t blkdev_max_block(struct block_device *bdev, unsigned int size)
+{
+       sector_t retval = ~((sector_t)0);
+       loff_t sz = i_size_read(bdev->bd_inode);
+
+       if (sz) {
+               unsigned int sizebits = blksize_bits(size);
+               retval = (sz >> sizebits);
+       }
+       return retval;
+}
+
 /*
  * Initialise the state of a blockdev page's buffers.
  */ 
@@ -921,7 +933,7 @@ init_page_buffers(struct page *page, struct block_device *bdev,
        struct buffer_head *head = page_buffers(page);
        struct buffer_head *bh = head;
        int uptodate = PageUptodate(page);
-       sector_t end_block = blkdev_max_block(I_BDEV(bdev->bd_inode));
+       sector_t end_block = blkdev_max_block(I_BDEV(bdev->bd_inode), size);
 
        do {
                if (!buffer_mapped(bh)) {
@@ -1553,6 +1565,28 @@ void unmap_underlying_metadata(struct block_device *bdev, sector_t block)
 EXPORT_SYMBOL(unmap_underlying_metadata);
 
 /*
+ * Size is a power-of-two in the range 512..PAGE_SIZE,
+ * and the case we care about most is PAGE_SIZE.
+ *
+ * So this *could* possibly be written with those
+ * constraints in mind (relevant mostly if some
+ * architecture has a slow bit-scan instruction)
+ */
+static inline int block_size_bits(unsigned int blocksize)
+{
+       return ilog2(blocksize);
+}
+
+static struct buffer_head *create_page_buffers(struct page *page, struct inode *inode, unsigned int b_state)
+{
+       BUG_ON(!PageLocked(page));
+
+       if (!page_has_buffers(page))
+               create_empty_buffers(page, 1 << ACCESS_ONCE(inode->i_blkbits), b_state);
+       return page_buffers(page);
+}
+
+/*
  * NOTE! All mapped/uptodate combinations are valid:
  *
  *     Mapped  Uptodate        Meaning
@@ -1589,19 +1623,13 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
        sector_t block;
        sector_t last_block;
        struct buffer_head *bh, *head;
-       const unsigned blocksize = 1 << inode->i_blkbits;
+       unsigned int blocksize, bbits;
        int nr_underway = 0;
        int write_op = (wbc->sync_mode == WB_SYNC_ALL ?
                        WRITE_SYNC : WRITE);
 
-       BUG_ON(!PageLocked(page));
-
-       last_block = (i_size_read(inode) - 1) >> inode->i_blkbits;
-
-       if (!page_has_buffers(page)) {
-               create_empty_buffers(page, blocksize,
+       head = create_page_buffers(page, inode,
                                        (1 << BH_Dirty)|(1 << BH_Uptodate));
-       }
 
        /*
         * Be very careful.  We have no exclusion from __set_page_dirty_buffers
@@ -1613,9 +1641,12 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
         * handle that here by just cleaning them.
         */
 
-       block = (sector_t)page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
-       head = page_buffers(page);
        bh = head;
+       blocksize = bh->b_size;
+       bbits = block_size_bits(blocksize);
+
+       block = (sector_t)page->index << (PAGE_CACHE_SHIFT - bbits);
+       last_block = (i_size_read(inode) - 1) >> bbits;
 
        /*
         * Get all the dirty buffers mapped to disk addresses and
@@ -1806,12 +1837,10 @@ int __block_write_begin(struct page *page, loff_t pos, unsigned len,
        BUG_ON(to > PAGE_CACHE_SIZE);
        BUG_ON(from > to);
 
-       blocksize = 1 << inode->i_blkbits;
-       if (!page_has_buffers(page))
-               create_empty_buffers(page, blocksize, 0);
-       head = page_buffers(page);
+       head = create_page_buffers(page, inode, 0);
+       blocksize = head->b_size;
+       bbits = block_size_bits(blocksize);
 
-       bbits = inode->i_blkbits;
        block = (sector_t)page->index << (PAGE_CACHE_SHIFT - bbits);
 
        for(bh = head, block_start = 0; bh != head || !block_start;
@@ -1881,11 +1910,11 @@ static int __block_commit_write(struct inode *inode, struct page *page,
        unsigned blocksize;
        struct buffer_head *bh, *head;
 
-       blocksize = 1 << inode->i_blkbits;
+       bh = head = page_buffers(page);
+       blocksize = bh->b_size;
 
-       for(bh = head = page_buffers(page), block_start = 0;
-           bh != head || !block_start;
-           block_start=block_end, bh = bh->b_this_page) {
+       block_start = 0;
+       do {
                block_end = block_start + blocksize;
                if (block_end <= from || block_start >= to) {
                        if (!buffer_uptodate(bh))
@@ -1895,7 +1924,10 @@ static int __block_commit_write(struct inode *inode, struct page *page,
                        mark_buffer_dirty(bh);
                }
                clear_buffer_new(bh);
-       }
+
+               block_start = block_end;
+               bh = bh->b_this_page;
+       } while (bh != head);
 
        /*
         * If this is a partial write which happened to make all buffers
@@ -2020,7 +2052,6 @@ EXPORT_SYMBOL(generic_write_end);
 int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc,
                                        unsigned long from)
 {
-       struct inode *inode = page->mapping->host;
        unsigned block_start, block_end, blocksize;
        unsigned to;
        struct buffer_head *bh, *head;
@@ -2029,13 +2060,13 @@ int block_is_partially_uptodate(struct page *page, read_descriptor_t *desc,
        if (!page_has_buffers(page))
                return 0;
 
-       blocksize = 1 << inode->i_blkbits;
+       head = page_buffers(page);
+       blocksize = head->b_size;
        to = min_t(unsigned, PAGE_CACHE_SIZE - from, desc->count);
        to = from + to;
        if (from < blocksize && to > PAGE_CACHE_SIZE - blocksize)
                return 0;
 
-       head = page_buffers(page);
        bh = head;
        block_start = 0;
        do {
@@ -2068,18 +2099,16 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
        struct inode *inode = page->mapping->host;
        sector_t iblock, lblock;
        struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE];
-       unsigned int blocksize;
+       unsigned int blocksize, bbits;
        int nr, i;
        int fully_mapped = 1;
 
-       BUG_ON(!PageLocked(page));
-       blocksize = 1 << inode->i_blkbits;
-       if (!page_has_buffers(page))
-               create_empty_buffers(page, blocksize, 0);
-       head = page_buffers(page);
+       head = create_page_buffers(page, inode, 0);
+       blocksize = head->b_size;
+       bbits = block_size_bits(blocksize);
 
-       iblock = (sector_t)page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
-       lblock = (i_size_read(inode)+blocksize-1) >> inode->i_blkbits;
+       iblock = (sector_t)page->index << (PAGE_CACHE_SHIFT - bbits);
+       lblock = (i_size_read(inode)+blocksize-1) >> bbits;
        bh = head;
        nr = 0;
        i = 0;
@@ -2864,6 +2893,55 @@ static void end_bio_bh_io_sync(struct bio *bio, int err)
        bio_put(bio);
 }
 
+/*
+ * This allows us to do IO even on the odd last sectors
+ * of a device, even if the bh block size is some multiple
+ * of the physical sector size.
+ *
+ * We'll just truncate the bio to the size of the device,
+ * and clear the end of the buffer head manually.
+ *
+ * Truly out-of-range accesses will turn into actual IO
+ * errors, this only handles the "we need to be able to
+ * do IO at the final sector" case.
+ */
+static void guard_bh_eod(int rw, struct bio *bio, struct buffer_head *bh)
+{
+       sector_t maxsector;
+       unsigned bytes;
+
+       maxsector = i_size_read(bio->bi_bdev->bd_inode) >> 9;
+       if (!maxsector)
+               return;
+
+       /*
+        * If the *whole* IO is past the end of the device,
+        * let it through, and the IO layer will turn it into
+        * an EIO.
+        */
+       if (unlikely(bio->bi_sector >= maxsector))
+               return;
+
+       maxsector -= bio->bi_sector;
+       bytes = bio->bi_size;
+       if (likely((bytes >> 9) <= maxsector))
+               return;
+
+       /* Uhhuh. We've got a bh that straddles the device size! */
+       bytes = maxsector << 9;
+
+       /* Truncate the bio.. */
+       bio->bi_size = bytes;
+       bio->bi_io_vec[0].bv_len = bytes;
+
+       /* ..and clear the end of the buffer for reads */
+       if ((rw & RW_MASK) == READ) {
+               void *kaddr = kmap_atomic(bh->b_page);
+               memset(kaddr + bh_offset(bh) + bytes, 0, bh->b_size - bytes);
+               kunmap_atomic(kaddr);
+       }
+}
+
 int submit_bh(int rw, struct buffer_head * bh)
 {
        struct bio *bio;
@@ -2900,6 +2978,9 @@ int submit_bh(int rw, struct buffer_head * bh)
        bio->bi_end_io = end_bio_bh_io_sync;
        bio->bi_private = bh;
 
+       /* Take care of bh's that straddle the end of the device */
+       guard_bh_eod(rw, bio, bh);
+
        bio_get(bio);
        submit_bio(rw, bio);
 
index 02ce909..9349bb3 100644 (file)
@@ -90,6 +90,8 @@ static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len,
                *max_len = handle_length;
                type = 255;
        }
+       if (dentry)
+               dput(dentry);
        return type;
 }
 
index 3f152b9..afc2bb6 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 fc783e2..0fb15bb 100644 (file)
@@ -225,6 +225,13 @@ sid_to_str(struct cifs_sid *sidptr, char *sidstr)
 }
 
 static void
+cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
+{
+       memcpy(dst, src, sizeof(*dst));
+       dst->num_subauth = min_t(u8, src->num_subauth, NUM_SUBAUTHS);
+}
+
+static void
 id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr,
                struct cifs_sid_id **psidid, char *typestr)
 {
@@ -248,7 +255,7 @@ id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr,
                }
        }
 
-       memcpy(&(*psidid)->sid, sidptr, sizeof(struct cifs_sid));
+       cifs_copy_sid(&(*psidid)->sid, sidptr);
        (*psidid)->time = jiffies - (SID_MAP_RETRY + 1);
        (*psidid)->refcount = 0;
 
@@ -354,7 +361,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
         * 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));
+               cifs_copy_sid(ssid, &psidid->sid);
                psidid->time = jiffies; /* update ts for accessing */
                goto id_sid_out;
        }
@@ -370,14 +377,14 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
                if (IS_ERR(sidkey)) {
                        rc = -EINVAL;
                        cFYI(1, "%s: Can't map and id to a SID", __func__);
+               } else if (sidkey->datalen < sizeof(struct cifs_sid)) {
+                       rc = -EIO;
+                       cFYI(1, "%s: Downcall contained malformed key "
+                               "(datalen=%hu)", __func__, sidkey->datalen);
                } 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));
+                       cifs_copy_sid(&psidid->sid, lsid);
+                       cifs_copy_sid(ssid, &psidid->sid);
                        set_bit(SID_ID_MAPPED, &psidid->state);
                        key_put(sidkey);
                        kfree(psidid->sidstr);
@@ -396,7 +403,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
                        return rc;
                }
                if (test_bit(SID_ID_MAPPED, &psidid->state))
-                       memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid));
+                       cifs_copy_sid(ssid, &psidid->sid);
                else
                        rc = -EINVAL;
        }
@@ -675,8 +682,6 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
 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 +697,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;
 }
@@ -1120,8 +1113,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 +1131,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;
                }
index 7c0a812..d3671f2 100644 (file)
@@ -398,7 +398,16 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
         * in network traffic in the other paths.
         */
        if (!(oflags & O_CREAT)) {
-               struct dentry *res = cifs_lookup(inode, direntry, 0);
+               struct dentry *res;
+
+               /*
+                * Check for hashed negative dentry. We have already revalidated
+                * the dentry and it is fine. No need to perform another lookup.
+                */
+               if (!d_unhashed(direntry))
+                       return -ENOENT;
+
+               res = cifs_lookup(inode, direntry, 0);
                if (IS_ERR(res))
                        return PTR_ERR(res);
 
index edb25b4..70b6f4c 100644 (file)
@@ -1794,7 +1794,6 @@ static int cifs_writepages(struct address_space *mapping,
        struct TCP_Server_Info *server;
        struct page *page;
        int rc = 0;
-       loff_t isize = i_size_read(mapping->host);
 
        /*
         * If wsize is smaller than the page cache size, default to writing
@@ -1899,7 +1898,7 @@ retry:
                         */
                        set_page_writeback(page);
 
-                       if (page_offset(page) >= isize) {
+                       if (page_offset(page) >= i_size_read(mapping->host)) {
                                done = true;
                                unlock_page(page);
                                end_page_writeback(page);
@@ -1932,7 +1931,8 @@ retry:
                wdata->offset = page_offset(wdata->pages[0]);
                wdata->pagesz = PAGE_CACHE_SIZE;
                wdata->tailsz =
-                       min(isize - page_offset(wdata->pages[nr_pages - 1]),
+                       min(i_size_read(mapping->host) -
+                           page_offset(wdata->pages[nr_pages - 1]),
                            (loff_t)PAGE_CACHE_SIZE);
                wdata->bytes = ((nr_pages - 1) * PAGE_CACHE_SIZE) +
                                        wdata->tailsz;
index f9b5d3d..1c576e8 100644 (file)
@@ -86,14 +86,17 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name,
 
        dentry = d_lookup(parent, name);
        if (dentry) {
+               int err;
                inode = dentry->d_inode;
                /* update inode in place if i_ino didn't change */
                if (inode && CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) {
                        cifs_fattr_to_inode(inode, fattr);
                        return dentry;
                }
-               d_drop(dentry);
+               err = d_invalidate(dentry);
                dput(dentry);
+               if (err)
+                       return NULL;
        }
 
        dentry = d_alloc(parent, name);
index 56cc4be..34cea27 100644 (file)
@@ -766,7 +766,6 @@ smb_set_file_info(struct inode *inode, const char *full_path,
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
        struct tcon_link *tlink = NULL;
        struct cifs_tcon *tcon;
-       FILE_BASIC_INFO info_buf;
 
        /* if the file is already open for write, just use that fileid */
        open_file = find_writable_file(cinode, true);
@@ -817,7 +816,7 @@ smb_set_file_info(struct inode *inode, const char *full_path,
        netpid = current->tgid;
 
 set_via_filehandle:
-       rc = CIFSSMBSetFileInfo(xid, tcon, &info_buf, netfid, netpid);
+       rc = CIFSSMBSetFileInfo(xid, tcon, buf, netfid, netpid);
        if (!rc)
                cinode->cifsAttrs = le32_to_cpu(buf->Attributes);
 
index f505402..4c6285f 100644 (file)
@@ -210,6 +210,8 @@ static int do_video_set_spu_palette(unsigned int fd, unsigned int cmd,
 
        err  = get_user(palp, &up->palette);
        err |= get_user(length, &up->length);
+       if (err)
+               return -EFAULT;
 
        up_native = compat_alloc_user_space(sizeof(struct video_spu_palette));
        err  = put_user(compat_ptr(palp), &up_native->palette);
index fd37fac..ce47379 100644 (file)
@@ -450,11 +450,12 @@ static int umh_pipe_setup(struct subprocess_info *info, struct cred *new)
 
        cp->file = files[1];
 
-       replace_fd(0, files[0], 0);
+       err = replace_fd(0, files[0], 0);
+       fput(files[0]);
        /* and disallow core files too */
        current->signal->rlim[RLIMIT_CORE] = (struct rlimit){1, 1};
 
-       return 0;
+       return err;
 }
 
 void do_coredump(siginfo_t *siginfo, struct pt_regs *regs)
index f86c720..cf5b44b 100644 (file)
@@ -540,6 +540,7 @@ static int get_more_blocks(struct dio *dio, struct dio_submit *sdio,
        sector_t fs_endblk;     /* Into file, in filesystem-sized blocks */
        unsigned long fs_count; /* Number of filesystem-sized blocks */
        int create;
+       unsigned int i_blkbits = sdio->blkbits + sdio->blkfactor;
 
        /*
         * If there was a memory error and we've overwritten all the
@@ -554,7 +555,7 @@ static int get_more_blocks(struct dio *dio, struct dio_submit *sdio,
                fs_count = fs_endblk - fs_startblk + 1;
 
                map_bh->b_state = 0;
-               map_bh->b_size = fs_count << dio->inode->i_blkbits;
+               map_bh->b_size = fs_count << i_blkbits;
 
                /*
                 * For writes inside i_size on a DIO_SKIP_HOLES filesystem we
@@ -1053,7 +1054,8 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
        int seg;
        size_t size;
        unsigned long addr;
-       unsigned blkbits = inode->i_blkbits;
+       unsigned i_blkbits = ACCESS_ONCE(inode->i_blkbits);
+       unsigned blkbits = i_blkbits;
        unsigned blocksize_mask = (1 << blkbits) - 1;
        ssize_t retval = -EINVAL;
        loff_t end = offset;
@@ -1149,7 +1151,7 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
        dio->inode = inode;
        dio->rw = rw;
        sdio.blkbits = blkbits;
-       sdio.blkfactor = inode->i_blkbits - blkbits;
+       sdio.blkfactor = i_blkbits - blkbits;
        sdio.block_in_file = offset >> blkbits;
 
        sdio.get_block = get_block;
index da72250..cd96649 100644 (file)
@@ -346,7 +346,7 @@ static inline struct epitem *ep_item_from_epqueue(poll_table *p)
 /* Tells if the epoll_ctl(2) operation needs an event copy from userspace */
 static inline int ep_op_has_event(int op)
 {
-       return op == EPOLL_CTL_ADD || op == EPOLL_CTL_MOD;
+       return op != EPOLL_CTL_DEL;
 }
 
 /* Initialize the poll safe wake up structure */
@@ -676,34 +676,6 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
        return 0;
 }
 
-/*
- * Disables a "struct epitem" in the eventpoll set. Returns -EBUSY if the item
- * had no event flags set, indicating that another thread may be currently
- * handling that item's events (in the case that EPOLLONESHOT was being
- * used). Otherwise a zero result indicates that the item has been disabled
- * from receiving events. A disabled item may be re-enabled via
- * EPOLL_CTL_MOD. Must be called with "mtx" held.
- */
-static int ep_disable(struct eventpoll *ep, struct epitem *epi)
-{
-       int result = 0;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ep->lock, flags);
-       if (epi->event.events & ~EP_PRIVATE_BITS) {
-               if (ep_is_linked(&epi->rdllink))
-                       list_del_init(&epi->rdllink);
-               /* Ensure ep_poll_callback will not add epi back onto ready
-                  list: */
-               epi->event.events &= EP_PRIVATE_BITS;
-               }
-       else
-               result = -EBUSY;
-       spin_unlock_irqrestore(&ep->lock, flags);
-
-       return result;
-}
-
 static void ep_free(struct eventpoll *ep)
 {
        struct rb_node *rbp;
@@ -1048,6 +1020,8 @@ static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi)
        rb_insert_color(&epi->rbn, &ep->rbr);
 }
 
+
+
 #define PATH_ARR_SIZE 5
 /*
  * These are the number paths of length 1 to 5, that we are allowing to emanate
@@ -1813,12 +1787,6 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
                } else
                        error = -ENOENT;
                break;
-       case EPOLL_CTL_DISABLE:
-               if (epi)
-                       error = ep_disable(ep, epi);
-               else
-                       error = -ENOENT;
-               break;
        }
        mutex_unlock(&ep->mtx);
 
index 8b9011b..0039055 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1083,7 +1083,8 @@ int flush_old_exec(struct linux_binprm * bprm)
        bprm->mm = NULL;                /* We're using it now */
 
        set_fs(USER_DS);
-       current->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD);
+       current->flags &=
+               ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD | PF_NOFREEZE);
        flush_thread();
        current->personality &= ~bprm->per_clear;
 
index 6c205d0..fa04d02 100644 (file)
@@ -469,7 +469,7 @@ static int parse_options(char *options, struct super_block *sb)
                        uid = make_kuid(current_user_ns(), option);
                        if (!uid_valid(uid)) {
                                ext2_msg(sb, KERN_ERR, "Invalid uid value %d", option);
-                               return -1;
+                               return 0;
 
                        }
                        sbi->s_resuid = uid;
@@ -480,7 +480,7 @@ static int parse_options(char *options, struct super_block *sb)
                        gid = make_kgid(current_user_ns(), option);
                        if (!gid_valid(gid)) {
                                ext2_msg(sb, KERN_ERR, "Invalid gid value %d", option);
-                               return -1;
+                               return 0;
                        }
                        sbi->s_resgid = gid;
                        break;
index 7320a66..22548f5 100644 (file)
@@ -2101,8 +2101,9 @@ int ext3_trim_fs(struct super_block *sb, struct fstrim_range *range)
        end = start + (range->len >> sb->s_blocksize_bits) - 1;
        minlen = range->minlen >> sb->s_blocksize_bits;
 
-       if (unlikely(minlen > EXT3_BLOCKS_PER_GROUP(sb)) ||
-           unlikely(start >= max_blks))
+       if (minlen > EXT3_BLOCKS_PER_GROUP(sb) ||
+           start >= max_blks ||
+           range->len < sb->s_blocksize)
                return -EINVAL;
        if (end >= max_blks)
                end = max_blks - 1;
index 8f4fdda..890b894 100644 (file)
@@ -46,8 +46,7 @@ static struct buffer_head *ext3_append(handle_t *handle,
 
        *block = inode->i_size >> inode->i_sb->s_blocksize_bits;
 
-       bh = ext3_bread(handle, inode, *block, 1, err);
-       if (bh) {
+       if ((bh = ext3_dir_bread(handle, inode, *block, 1, err))) {
                inode->i_size += inode->i_sb->s_blocksize;
                EXT3_I(inode)->i_disksize = inode->i_size;
                *err = ext3_journal_get_write_access(handle, bh);
@@ -339,8 +338,10 @@ dx_probe(struct qstr *entry, struct inode *dir,
        u32 hash;
 
        frame->bh = NULL;
-       if (!(bh = ext3_bread (NULL,dir, 0, 0, err)))
+       if (!(bh = ext3_dir_bread(NULL, dir, 0, 0, err))) {
+               *err = ERR_BAD_DX_DIR;
                goto fail;
+       }
        root = (struct dx_root *) bh->b_data;
        if (root->info.hash_version != DX_HASH_TEA &&
            root->info.hash_version != DX_HASH_HALF_MD4 &&
@@ -436,8 +437,10 @@ dx_probe(struct qstr *entry, struct inode *dir,
                frame->entries = entries;
                frame->at = at;
                if (!indirect--) return frame;
-               if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err)))
+               if (!(bh = ext3_dir_bread(NULL, dir, dx_get_block(at), 0, err))) {
+                       *err = ERR_BAD_DX_DIR;
                        goto fail2;
+               }
                at = entries = ((struct dx_node *) bh->b_data)->entries;
                if (dx_get_limit(entries) != dx_node_limit (dir)) {
                        ext3_warning(dir->i_sb, __func__,
@@ -535,8 +538,8 @@ static int ext3_htree_next_block(struct inode *dir, __u32 hash,
         * block so no check is necessary
         */
        while (num_frames--) {
-               if (!(bh = ext3_bread(NULL, dir, dx_get_block(p->at),
-                                     0, &err)))
+               if (!(bh = ext3_dir_bread(NULL, dir, dx_get_block(p->at),
+                                         0, &err)))
                        return err; /* Failure */
                p++;
                brelse (p->bh);
@@ -559,10 +562,11 @@ static int htree_dirblock_to_tree(struct file *dir_file,
 {
        struct buffer_head *bh;
        struct ext3_dir_entry_2 *de, *top;
-       int err, count = 0;
+       int err = 0, count = 0;
 
        dxtrace(printk("In htree dirblock_to_tree: block %d\n", block));
-       if (!(bh = ext3_bread (NULL, dir, block, 0, &err)))
+
+       if (!(bh = ext3_dir_bread(NULL, dir, block, 0, &err)))
                return err;
 
        de = (struct ext3_dir_entry_2 *) bh->b_data;
@@ -976,7 +980,7 @@ static struct buffer_head * ext3_dx_find_entry(struct inode *dir,
                return NULL;
        do {
                block = dx_get_block(frame->at);
-               if (!(bh = ext3_bread (NULL,dir, block, 0, err)))
+               if (!(bh = ext3_dir_bread (NULL, dir, block, 0, err)))
                        goto errout;
 
                retval = search_dirblock(bh, dir, entry,
@@ -1458,9 +1462,9 @@ static int ext3_add_entry (handle_t *handle, struct dentry *dentry,
        }
        blocks = dir->i_size >> sb->s_blocksize_bits;
        for (block = 0; block < blocks; block++) {
-               bh = ext3_bread(handle, dir, block, 0, &retval);
-               if(!bh)
+               if (!(bh = ext3_dir_bread(handle, dir, block, 0, &retval)))
                        return retval;
+
                retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh);
                if (retval != -ENOSPC)
                        return retval;
@@ -1500,7 +1504,7 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
        entries = frame->entries;
        at = frame->at;
 
-       if (!(bh = ext3_bread(handle,dir, dx_get_block(frame->at), 0, &err)))
+       if (!(bh = ext3_dir_bread(handle, dir, dx_get_block(frame->at), 0, &err)))
                goto cleanup;
 
        BUFFER_TRACE(bh, "get_write_access");
@@ -1790,8 +1794,7 @@ retry:
        inode->i_op = &ext3_dir_inode_operations;
        inode->i_fop = &ext3_dir_operations;
        inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;
-       dir_block = ext3_bread (handle, inode, 0, 1, &err);
-       if (!dir_block)
+       if (!(dir_block = ext3_dir_bread(handle, inode, 0, 1, &err)))
                goto out_clear_inode;
 
        BUFFER_TRACE(dir_block, "get_write_access");
@@ -1859,7 +1862,7 @@ static int empty_dir (struct inode * inode)
 
        sb = inode->i_sb;
        if (inode->i_size < EXT3_DIR_REC_LEN(1) + EXT3_DIR_REC_LEN(2) ||
-           !(bh = ext3_bread (NULL, inode, 0, 0, &err))) {
+           !(bh = ext3_dir_bread(NULL, inode, 0, 0, &err))) {
                if (err)
                        ext3_error(inode->i_sb, __func__,
                                   "error %d reading directory #%lu offset 0",
@@ -1890,9 +1893,8 @@ static int empty_dir (struct inode * inode)
                        (void *) de >= (void *) (bh->b_data+sb->s_blocksize)) {
                        err = 0;
                        brelse (bh);
-                       bh = ext3_bread (NULL, inode,
-                               offset >> EXT3_BLOCK_SIZE_BITS(sb), 0, &err);
-                       if (!bh) {
+                       if (!(bh = ext3_dir_bread (NULL, inode,
+                               offset >> EXT3_BLOCK_SIZE_BITS(sb), 0, &err))) {
                                if (err)
                                        ext3_error(sb, __func__,
                                                   "error %d reading directory"
@@ -2388,7 +2390,7 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
                                goto end_rename;
                }
                retval = -EIO;
-               dir_bh = ext3_bread (handle, old_inode, 0, 0, &retval);
+               dir_bh = ext3_dir_bread(handle, old_inode, 0, 0, &retval);
                if (!dir_bh)
                        goto end_rename;
                if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino)
index f2ce2b0..46304d8 100644 (file)
@@ -6,3 +6,22 @@
 */
 
 extern struct dentry *ext3_get_parent(struct dentry *child);
+
+static inline struct buffer_head *ext3_dir_bread(handle_t *handle,
+                                                struct inode *inode,
+                                                int block, int create,
+                                                int *err)
+{
+       struct buffer_head *bh;
+
+       bh = ext3_bread(handle, inode, block, create, err);
+
+       if (!bh && !(*err)) {
+               *err = -EIO;
+               ext3_error(inode->i_sb, __func__,
+                          "Directory hole detected on inode %lu\n",
+                          inode->i_ino);
+               return NULL;
+       }
+       return bh;
+}
index 29e7971..5366393 100644 (file)
@@ -1001,7 +1001,7 @@ static int parse_options (char *options, struct super_block *sb,
                        uid = make_kuid(current_user_ns(), option);
                        if (!uid_valid(uid)) {
                                ext3_msg(sb, KERN_ERR, "Invalid uid value %d", option);
-                               return -1;
+                               return 0;
 
                        }
                        sbi->s_resuid = uid;
@@ -1012,7 +1012,7 @@ static int parse_options (char *options, struct super_block *sb,
                        gid = make_kgid(current_user_ns(), option);
                        if (!gid_valid(gid)) {
                                ext3_msg(sb, KERN_ERR, "Invalid gid value %d", option);
-                               return -1;
+                               return 0;
                        }
                        sbi->s_resgid = gid;
                        break;
index 1b50890..cf18217 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 5c2d181..3285aa5 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 3ab2539..3c20de1 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 bfa65b4..b4323ba 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 1c94cca..7011ac9 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 fa36372..3a100e7 100644 (file)
@@ -725,6 +725,10 @@ repeat_in_this_group:
                                   "inode=%lu", ino + 1);
                        continue;
                }
+               BUFFER_TRACE(inode_bitmap_bh, "get_write_access");
+               err = ext4_journal_get_write_access(handle, inode_bitmap_bh);
+               if (err)
+                       goto fail;
                ext4_lock_group(sb, group);
                ret2 = ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data);
                ext4_unlock_group(sb, group);
@@ -738,6 +742,11 @@ repeat_in_this_group:
        goto out;
 
 got:
+       BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata");
+       err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh);
+       if (err)
+               goto fail;
+
        /* We may have to initialize the block bitmap if it isn't already */
        if (ext4_has_group_desc_csum(sb) &&
            gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
@@ -762,9 +771,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);
@@ -773,11 +780,6 @@ got:
                        goto fail;
        }
 
-       BUFFER_TRACE(inode_bitmap_bh, "get_write_access");
-       err = ext4_journal_get_write_access(handle, inode_bitmap_bh);
-       if (err)
-               goto fail;
-
        BUFFER_TRACE(group_desc_bh, "get_write_access");
        err = ext4_journal_get_write_access(handle, group_desc_bh);
        if (err)
@@ -825,11 +827,6 @@ got:
        }
        ext4_unlock_group(sb, group);
 
-       BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata");
-       err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh);
-       if (err)
-               goto fail;
-
        BUFFER_TRACE(group_desc_bh, "call ext4_handle_dirty_metadata");
        err = ext4_handle_dirty_metadata(handle, NULL, group_desc_bh);
        if (err)
index f8b27bf..526e553 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 7a75e10..47bf06a 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 7265a03..80928f7 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 d3b5fa8..eff2316 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -685,7 +685,6 @@ void do_close_on_exec(struct files_struct *files)
        struct fdtable *fdt;
 
        /* exec unshares first */
-       BUG_ON(atomic_read(&files->count) != 1);
        spin_lock(&files->file_lock);
        for (i = 0; ; i++) {
                unsigned long set;
@@ -900,7 +899,7 @@ int replace_fd(unsigned fd, struct file *file, unsigned flags)
                return __close_fd(files, fd);
 
        if (fd >= rlimit(RLIMIT_NOFILE))
-               return -EMFILE;
+               return -EBADF;
 
        spin_lock(&files->file_lock);
        err = expand_files(files, fd);
@@ -926,7 +925,7 @@ SYSCALL_DEFINE3(dup3, unsigned int, oldfd, unsigned int, newfd, int, flags)
                return -EINVAL;
 
        if (newfd >= rlimit(RLIMIT_NOFILE))
-               return -EMFILE;
+               return -EBADF;
 
        spin_lock(&files->file_lock);
        err = expand_files(files, newfd);
@@ -995,16 +994,18 @@ int iterate_fd(struct files_struct *files, unsigned n,
                const void *p)
 {
        struct fdtable *fdt;
-       struct file *file;
        int res = 0;
        if (!files)
                return 0;
        spin_lock(&files->file_lock);
-       fdt = files_fdtable(files);
-       while (!res && n < fdt->max_fds) {
-               file = rcu_dereference_check_fdtable(files, fdt->fd[n++]);
-               if (file)
-                       res = f(p, file, n);
+       for (fdt = files_fdtable(files); n < fdt->max_fds; n++) {
+               struct file *file;
+               file = rcu_dereference_check_fdtable(files, fdt->fd[n]);
+               if (!file)
+                       continue;
+               res = f(p, file, n);
+               if (res)
+                       break;
        }
        spin_unlock(&files->file_lock);
        return res;
index 51ea267..3e3422f 100644 (file)
@@ -228,6 +228,8 @@ static void requeue_io(struct inode *inode, struct bdi_writeback *wb)
 static void inode_sync_complete(struct inode *inode)
 {
        inode->i_state &= ~I_SYNC;
+       /* If inode is clean an unused, put it into LRU now... */
+       inode_add_lru(inode);
        /* Waiters must see I_SYNC cleared before being woken up */
        smp_mb();
        wake_up_bit(&inode->i_state, __I_SYNC);
index 0def050..e056b4c 100644 (file)
@@ -516,15 +516,13 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma)
                struct gfs2_holder i_gh;
                int error;
 
-               gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
-               error = gfs2_glock_nq(&i_gh);
-               if (error == 0) {
-                       file_accessed(file);
-                       gfs2_glock_dq(&i_gh);
-               }
-               gfs2_holder_uninit(&i_gh);
+               error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY,
+                                          &i_gh);
                if (error)
                        return error;
+               /* grab lock to update inode */
+               gfs2_glock_dq_uninit(&i_gh);
+               file_accessed(file);
        }
        vma->vm_ops = &gfs2_vm_ops;
 
@@ -677,10 +675,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 8ff95a2..9ceccb1 100644 (file)
@@ -393,12 +393,10 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
        struct gfs2_meta_header *mh;
        struct gfs2_trans *tr;
 
-       lock_buffer(bd->bd_bh);
-       gfs2_log_lock(sdp);
        tr = current->journal_info;
        tr->tr_touched = 1;
        if (!list_empty(&bd->bd_list))
-               goto out;
+               return;
        set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
        set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
        mh = (struct gfs2_meta_header *)bd->bd_bh->b_data;
@@ -414,9 +412,6 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
        sdp->sd_log_num_buf++;
        list_add(&bd->bd_list, &sdp->sd_log_le_buf);
        tr->tr_num_buf_new++;
-out:
-       gfs2_log_unlock(sdp);
-       unlock_buffer(bd->bd_bh);
 }
 
 static void gfs2_check_magic(struct buffer_head *bh)
@@ -621,7 +616,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 +628,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) {
@@ -777,12 +770,10 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
        struct address_space *mapping = bd->bd_bh->b_page->mapping;
        struct gfs2_inode *ip = GFS2_I(mapping->host);
 
-       lock_buffer(bd->bd_bh);
-       gfs2_log_lock(sdp);
        if (tr)
                tr->tr_touched = 1;
        if (!list_empty(&bd->bd_list))
-               goto out;
+               return;
        set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
        set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
        if (gfs2_is_jdata(ip)) {
@@ -793,9 +784,6 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
        } else {
                list_add_tail(&bd->bd_list, &sdp->sd_log_le_ordered);
        }
-out:
-       gfs2_log_unlock(sdp);
-       unlock_buffer(bd->bd_bh);
 }
 
 /**
index 40c4b0d..c5af8e1 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 3cc402c..38fe18f 100644 (file)
@@ -553,7 +553,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 +560,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 +570,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 +1262,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 +1272,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 +1302,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 +1333,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 bc73726..d648867 100644 (file)
@@ -810,7 +810,8 @@ static void gfs2_dirty_inode(struct inode *inode, int flags)
                        return;
                }
                need_unlock = 1;
-       }
+       } else if (WARN_ON_ONCE(ip->i_gl->gl_state != LM_ST_EXCLUSIVE))
+               return;
 
        if (current->journal_info == NULL) {
                ret = gfs2_trans_begin(sdp, RES_DINODE, 0);
index adbd278..4136270 100644 (file)
@@ -155,14 +155,22 @@ void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta)
        struct gfs2_sbd *sdp = gl->gl_sbd;
        struct gfs2_bufdata *bd;
 
+       lock_buffer(bh);
+       gfs2_log_lock(sdp);
        bd = bh->b_private;
        if (bd)
                gfs2_assert(sdp, bd->bd_gl == gl);
        else {
+               gfs2_log_unlock(sdp);
+               unlock_buffer(bh);
                gfs2_attach_bufdata(gl, bh, meta);
                bd = bh->b_private;
+               lock_buffer(bh);
+               gfs2_log_lock(sdp);
        }
        lops_add(sdp, bd);
+       gfs2_log_unlock(sdp);
+       unlock_buffer(bh);
 }
 
 void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
index b03c719..64999f1 100644 (file)
@@ -408,6 +408,19 @@ static void inode_lru_list_add(struct inode *inode)
        spin_unlock(&inode->i_sb->s_inode_lru_lock);
 }
 
+/*
+ * Add inode to LRU if needed (inode is unused and clean).
+ *
+ * Needs inode->i_lock held.
+ */
+void inode_add_lru(struct inode *inode)
+{
+       if (!(inode->i_state & (I_DIRTY | I_SYNC | I_FREEING | I_WILL_FREE)) &&
+           !atomic_read(&inode->i_count) && inode->i_sb->s_flags & MS_ACTIVE)
+               inode_lru_list_add(inode);
+}
+
+
 static void inode_lru_list_del(struct inode *inode)
 {
        spin_lock(&inode->i_sb->s_inode_lru_lock);
@@ -1390,8 +1403,7 @@ static void iput_final(struct inode *inode)
 
        if (!drop && (sb->s_flags & MS_ACTIVE)) {
                inode->i_state |= I_REFERENCED;
-               if (!(inode->i_state & (I_DIRTY|I_SYNC)))
-                       inode_lru_list_add(inode);
+               inode_add_lru(inode);
                spin_unlock(&inode->i_lock);
                return;
        }
index 916b7cb..2f6af7f 100644 (file)
@@ -110,6 +110,7 @@ extern int open_check_o_direct(struct file *f);
  * inode.c
  */
 extern spinlock_t inode_sb_list_lock;
+extern void inode_add_lru(struct inode *inode);
 
 /*
  * fs-writeback.c
index 78b7f84..7f5120b 100644 (file)
@@ -1961,7 +1961,9 @@ retry:
                        spin_unlock(&journal->j_list_lock);
                        jbd_unlock_bh_state(bh);
                        spin_unlock(&journal->j_state_lock);
+                       unlock_buffer(bh);
                        log_wait_commit(journal, tid);
+                       lock_buffer(bh);
                        goto retry;
                }
                /*
index 60ef3fb..1506673 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 9947563..dfcd503 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 d269ada..982d267 100644 (file)
@@ -223,7 +223,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;
 }
index e4fb3ba..3d7e09b 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);
 }
 
index 3009a36..21171f0 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 d1895f3..5f4cdf3 100644 (file)
@@ -705,8 +705,8 @@ static inline void put_link(struct nameidata *nd, struct path *link, void *cooki
        path_put(link);
 }
 
-int sysctl_protected_symlinks __read_mostly = 1;
-int sysctl_protected_hardlinks __read_mostly = 1;
+int sysctl_protected_symlinks __read_mostly = 0;
+int sysctl_protected_hardlinks __read_mostly = 0;
 
 /**
  * may_follow_link - Check symlink following for unsafe situations
@@ -2131,6 +2131,11 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
        if (!len)
                return ERR_PTR(-EACCES);
 
+       if (unlikely(name[0] == '.')) {
+               if (len < 2 || (len == 2 && name[1] == '.'))
+                       return ERR_PTR(-EACCES);
+       }
+
        while (len--) {
                c = *(const unsigned char *)name++;
                if (c == '/' || c == '\0')
index 9a521fb..5088b57 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 ce8cb92..b9e66b7 100644 (file)
@@ -450,7 +450,8 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)
                        nfs_refresh_inode(dentry->d_inode, entry->fattr);
                        goto out;
                } else {
-                       d_drop(dentry);
+                       if (d_invalidate(dentry) != 0)
+                               goto out;
                        dput(dentry);
                }
        }
@@ -1100,6 +1101,8 @@ out_set_verifier:
 out_zap_parent:
        nfs_zap_caches(dir);
  out_bad:
+       nfs_free_fattr(fattr);
+       nfs_free_fhandle(fhandle);
        nfs_mark_for_revalidate(dir);
        if (inode && S_ISDIR(inode->i_mode)) {
                /* Purge readdir caches. */
@@ -1112,8 +1115,6 @@ out_zap_parent:
                shrink_dcache_parent(dentry);
        }
        d_drop(dentry);
-       nfs_free_fattr(fattr);
-       nfs_free_fhandle(fhandle);
        dput(parent);
        dfprintk(LOOKUPCACHE, "NFS: %s(%s/%s) is invalid\n",
                        __func__, dentry->d_parent->d_name.name,
index 31c26c4..ca4b11e 100644 (file)
@@ -217,7 +217,7 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen)
 {
        char buf1[NFS_DNS_HOSTNAME_MAXLEN+1];
        struct nfs_dns_ent key, *item;
-       unsigned long ttl;
+       unsigned int ttl;
        ssize_t len;
        int ret = -EINVAL;
 
@@ -240,7 +240,8 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen)
        key.namelen = len;
        memset(&key.h, 0, sizeof(key.h));
 
-       ttl = get_expiry(&buf);
+       if (get_uint(&buf, &ttl) < 0)
+               goto out;
        if (ttl == 0)
                goto out;
        key.h.expiry_time = ttl + seconds_since_boot();
index 5c7325c..6fa01ae 100644 (file)
@@ -685,7 +685,10 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
        if (ctx->cred != NULL)
                put_rpccred(ctx->cred);
        dput(ctx->dentry);
-       nfs_sb_deactive(sb);
+       if (is_sync)
+               nfs_sb_deactive(sb);
+       else
+               nfs_sb_deactive_async(sb);
        kfree(ctx->mdsthreshold);
        kfree(ctx);
 }
index 59b133c..05521ca 100644 (file)
@@ -351,10 +351,12 @@ extern int __init register_nfs_fs(void);
 extern void __exit unregister_nfs_fs(void);
 extern void nfs_sb_active(struct super_block *sb);
 extern void nfs_sb_deactive(struct super_block *sb);
+extern void nfs_sb_deactive_async(struct super_block *sb);
 
 /* namespace.c */
+#define NFS_PATH_CANONICAL 1
 extern char *nfs_path(char **p, struct dentry *dentry,
-                     char *buffer, ssize_t buflen);
+                     char *buffer, ssize_t buflen, unsigned flags);
 extern struct vfsmount *nfs_d_automount(struct path *path);
 struct vfsmount *nfs_submount(struct nfs_server *, struct dentry *,
                              struct nfs_fh *, struct nfs_fattr *);
@@ -498,7 +500,7 @@ static inline char *nfs_devname(struct dentry *dentry,
                                char *buffer, ssize_t buflen)
 {
        char *dummy;
-       return nfs_path(&dummy, dentry, buffer, buflen);
+       return nfs_path(&dummy, dentry, buffer, buflen, NFS_PATH_CANONICAL);
 }
 
 /*
index 8e65c7f..015f71f 100644 (file)
@@ -181,7 +181,7 @@ int nfs_mount(struct nfs_mount_request *info)
        else
                msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC_MNT];
 
-       status = rpc_call_sync(mnt_clnt, &msg, 0);
+       status = rpc_call_sync(mnt_clnt, &msg, RPC_TASK_SOFT|RPC_TASK_TIMEOUT);
        rpc_shutdown_client(mnt_clnt);
 
        if (status < 0)
index 6559253..dd057bc 100644 (file)
@@ -33,6 +33,7 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ;
  * @dentry - pointer to dentry
  * @buffer - result buffer
  * @buflen - length of buffer
+ * @flags - options (see below)
  *
  * Helper function for constructing the server pathname
  * by arbitrary hashed dentry.
@@ -40,8 +41,14 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ;
  * This is mainly for use in figuring out the path on the
  * server side when automounting on top of an existing partition
  * and in generating /proc/mounts and friends.
+ *
+ * Supported flags:
+ * NFS_PATH_CANONICAL: ensure there is exactly one slash after
+ *                    the original device (export) name
+ *                    (if unset, the original name is returned verbatim)
  */
-char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen)
+char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen,
+              unsigned flags)
 {
        char *end;
        int namelen;
@@ -74,7 +81,7 @@ rename_retry:
                rcu_read_unlock();
                goto rename_retry;
        }
-       if (*end != '/') {
+       if ((flags & NFS_PATH_CANONICAL) && *end != '/') {
                if (--buflen < 0) {
                        spin_unlock(&dentry->d_lock);
                        rcu_read_unlock();
@@ -91,9 +98,11 @@ rename_retry:
                return end;
        }
        namelen = strlen(base);
-       /* Strip off excess slashes in base string */
-       while (namelen > 0 && base[namelen - 1] == '/')
-               namelen--;
+       if (flags & NFS_PATH_CANONICAL) {
+               /* Strip off excess slashes in base string */
+               while (namelen > 0 && base[namelen - 1] == '/')
+                       namelen--;
+       }
        buflen -= namelen;
        if (buflen < 0) {
                spin_unlock(&dentry->d_lock);
index 52d8472..2e45fd9 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:
@@ -331,7 +338,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);
 }
@@ -429,7 +438,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);
 }
@@ -739,7 +750,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;
index dca47d7..8c07241 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 3336d5e..a8eaa9b 100644 (file)
@@ -149,28 +149,6 @@ _data_server_lookup_locked(const struct list_head *dsaddrs)
 }
 
 /*
- * 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
  */
index 6a83780..549462e 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <linux/nfs_fs.h>
 #include "nfs4_fs.h"
+#include "internal.h"
 
 #define NFSDBG_FACILITY                NFSDBG_CLIENT
 
index 79fbb61..1e09eb7 100644 (file)
@@ -81,7 +81,8 @@ static char *nfs_path_component(const char *nfspath, const char *end)
 static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen)
 {
        char *limit;
-       char *path = nfs_path(&limit, dentry, buffer, buflen);
+       char *path = nfs_path(&limit, dentry, buffer, buflen,
+                             NFS_PATH_CANONICAL);
        if (!IS_ERR(path)) {
                char *path_component = nfs_path_component(path, limit);
                if (path_component)
index 68b21d8..5eec442 100644 (file)
@@ -339,8 +339,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
                        dprintk("%s ERROR: %d Reset session\n", __func__,
                                errorcode);
                        nfs4_schedule_session_recovery(clp->cl_session, errorcode);
-                       exception->retry = 1;
-                       break;
+                       goto wait_on_recovery;
 #endif /* defined(CONFIG_NFS_V4_1) */
                case -NFS4ERR_FILE_OPEN:
                        if (exception->timeout > HZ) {
@@ -1572,9 +1571,11 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
        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);
+                               &data->o_res.seq_res,
+                               task) != 0)
+               nfs_release_seqid(data->o_arg.seqid);
+       else
+               rpc_call_start(task);
        return;
 unlock_no_action:
        rcu_read_unlock();
@@ -1748,7 +1749,7 @@ static int nfs4_opendata_access(struct rpc_cred *cred,
 
        /* even though OPEN succeeded, access is denied. Close the file */
        nfs4_close_state(state, fmode);
-       return -NFS4ERR_ACCESS;
+       return -EACCES;
 }
 
 /*
@@ -2196,7 +2197,7 @@ static void nfs4_free_closedata(void *data)
        nfs4_put_open_state(calldata->state);
        nfs_free_seqid(calldata->arg.seqid);
        nfs4_put_state_owner(sp);
-       nfs_sb_deactive(sb);
+       nfs_sb_deactive_async(sb);
        kfree(calldata);
 }
 
@@ -2296,9 +2297,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
        if (nfs4_setup_sequence(NFS_SERVER(inode),
                                &calldata->arg.seq_args,
                                &calldata->res.seq_res,
-                               task))
-               goto out;
-       rpc_call_start(task);
+                               task) != 0)
+               nfs_release_seqid(calldata->arg.seqid);
+       else
+               rpc_call_start(task);
 out:
        dprintk("%s: done!\n", __func__);
 }
@@ -4529,6 +4531,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
                        if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN)
                                rpc_restart_call_prepare(task);
        }
+       nfs_release_seqid(calldata->arg.seqid);
 }
 
 static void nfs4_locku_prepare(struct rpc_task *task, void *data)
@@ -4545,9 +4548,11 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data)
        calldata->timestamp = jiffies;
        if (nfs4_setup_sequence(calldata->server,
                                &calldata->arg.seq_args,
-                               &calldata->res.seq_res, task))
-               return;
-       rpc_call_start(task);
+                               &calldata->res.seq_res,
+                               task) != 0)
+               nfs_release_seqid(calldata->arg.seqid);
+       else
+               rpc_call_start(task);
 }
 
 static const struct rpc_call_ops nfs4_locku_ops = {
@@ -4692,7 +4697,7 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
        /* Do we need to do an open_to_lock_owner? */
        if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) {
                if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0)
-                       return;
+                       goto out_release_lock_seqid;
                data->arg.open_stateid = &state->stateid;
                data->arg.new_lock_owner = 1;
                data->res.open_seqid = data->arg.open_seqid;
@@ -4701,10 +4706,15 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
        data->timestamp = jiffies;
        if (nfs4_setup_sequence(data->server,
                                &data->arg.seq_args,
-                               &data->res.seq_res, task))
+                               &data->res.seq_res,
+                               task) == 0) {
+               rpc_call_start(task);
                return;
-       rpc_call_start(task);
-       dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status);
+       }
+       nfs_release_seqid(data->arg.open_seqid);
+out_release_lock_seqid:
+       nfs_release_seqid(data->arg.lock_seqid);
+       dprintk("%s: done!, ret = %d\n", __func__, task->tk_status);
 }
 
 static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata)
@@ -5667,7 +5677,7 @@ static void nfs4_add_and_init_slots(struct nfs4_slot_table *tbl,
                tbl->slots = new;
                tbl->max_slots = max_slots;
        }
-       tbl->highest_used_slotid = -1;  /* no slot is currently used */
+       tbl->highest_used_slotid = NFS4_NO_SLOT;
        for (i = 0; i < tbl->max_slots; i++)
                tbl->slots[i].seq_nr = ivalue;
        spin_unlock(&tbl->slot_tbl_lock);
index be731e6..c6f9906 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 fe624c9..2878f97 100644 (file)
@@ -925,8 +925,8 @@ pnfs_find_alloc_layout(struct inode *ino,
        if (likely(nfsi->layout == NULL)) {     /* Won the race? */
                nfsi->layout = new;
                return new;
-       }
-       pnfs_free_layout_hdr(new);
+       } else if (new != NULL)
+               pnfs_free_layout_hdr(new);
 out_existing:
        pnfs_get_layout_hdr(nfsi->layout);
        return nfsi->layout;
index 2d722db..dbf7bba 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 e831bce..652d3f7 100644 (file)
@@ -54,6 +54,7 @@
 #include <linux/parser.h>
 #include <linux/nsproxy.h>
 #include <linux/rcupdate.h>
+#include <linux/kthread.h>
 
 #include <asm/uaccess.h>
 
@@ -415,6 +416,54 @@ void nfs_sb_deactive(struct super_block *sb)
 }
 EXPORT_SYMBOL_GPL(nfs_sb_deactive);
 
+static int nfs_deactivate_super_async_work(void *ptr)
+{
+       struct super_block *sb = ptr;
+
+       deactivate_super(sb);
+       module_put_and_exit(0);
+       return 0;
+}
+
+/*
+ * same effect as deactivate_super, but will do final unmount in kthread
+ * context
+ */
+static void nfs_deactivate_super_async(struct super_block *sb)
+{
+       struct task_struct *task;
+       char buf[INET6_ADDRSTRLEN + 1];
+       struct nfs_server *server = NFS_SB(sb);
+       struct nfs_client *clp = server->nfs_client;
+
+       if (!atomic_add_unless(&sb->s_active, -1, 1)) {
+               rcu_read_lock();
+               snprintf(buf, sizeof(buf),
+                       rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR));
+               rcu_read_unlock();
+
+               __module_get(THIS_MODULE);
+               task = kthread_run(nfs_deactivate_super_async_work, sb,
+                               "%s-deactivate-super", buf);
+               if (IS_ERR(task)) {
+                       pr_err("%s: kthread_run: %ld\n",
+                               __func__, PTR_ERR(task));
+                       /* make synchronous call and hope for the best */
+                       deactivate_super(sb);
+                       module_put(THIS_MODULE);
+               }
+       }
+}
+
+void nfs_sb_deactive_async(struct super_block *sb)
+{
+       struct nfs_server *server = NFS_SB(sb);
+
+       if (atomic_dec_and_test(&server->active))
+               nfs_deactivate_super_async(sb);
+}
+EXPORT_SYMBOL_GPL(nfs_sb_deactive_async);
+
 /*
  * Deliver file system statistics to userspace
  */
@@ -771,7 +820,7 @@ int nfs_show_devname(struct seq_file *m, struct dentry *root)
        int err = 0;
        if (!page)
                return -ENOMEM;
-       devname = nfs_path(&dummy, root, page, PAGE_SIZE);
+       devname = nfs_path(&dummy, root, page, PAGE_SIZE, 0);
        if (IS_ERR(devname))
                err = PTR_ERR(devname);
        else
index 13cea63..3f79c77 100644 (file)
@@ -95,7 +95,7 @@ static void nfs_async_unlink_release(void *calldata)
 
        nfs_dec_sillycount(data->dir);
        nfs_free_unlinkdata(data);
-       nfs_sb_deactive(sb);
+       nfs_sb_deactive_async(sb);
 }
 
 static void nfs_unlink_prepare(struct rpc_task *task, void *calldata)
index f35794b..a506360 100644 (file)
@@ -21,6 +21,7 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new)
                        if ((old->path.mnt == new->path.mnt) &&
                            (old->path.dentry == new->path.dentry))
                                return true;
+                       break;
                case (FSNOTIFY_EVENT_NONE):
                        return true;
                default:
index 721d692..6fcaeb8 100644 (file)
@@ -258,7 +258,8 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
        if (ret)
                goto out_close_fd;
 
-       fd_install(fd, f);
+       if (fd != FAN_NOFD)
+               fd_install(fd, f);
        return fanotify_event_metadata.event_len;
 
 out_close_fd:
index 144a967..9e28356 100644 (file)
@@ -873,6 +873,113 @@ static const struct file_operations proc_environ_operations = {
        .release        = mem_release,
 };
 
+static ssize_t oom_adj_read(struct file *file, char __user *buf, size_t count,
+                           loff_t *ppos)
+{
+       struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
+       char buffer[PROC_NUMBUF];
+       int oom_adj = OOM_ADJUST_MIN;
+       size_t len;
+       unsigned long flags;
+
+       if (!task)
+               return -ESRCH;
+       if (lock_task_sighand(task, &flags)) {
+               if (task->signal->oom_score_adj == OOM_SCORE_ADJ_MAX)
+                       oom_adj = OOM_ADJUST_MAX;
+               else
+                       oom_adj = (task->signal->oom_score_adj * -OOM_DISABLE) /
+                                 OOM_SCORE_ADJ_MAX;
+               unlock_task_sighand(task, &flags);
+       }
+       put_task_struct(task);
+       len = snprintf(buffer, sizeof(buffer), "%d\n", oom_adj);
+       return simple_read_from_buffer(buf, count, ppos, buffer, len);
+}
+
+static ssize_t oom_adj_write(struct file *file, const char __user *buf,
+                            size_t count, loff_t *ppos)
+{
+       struct task_struct *task;
+       char buffer[PROC_NUMBUF];
+       int oom_adj;
+       unsigned long flags;
+       int err;
+
+       memset(buffer, 0, sizeof(buffer));
+       if (count > sizeof(buffer) - 1)
+               count = sizeof(buffer) - 1;
+       if (copy_from_user(buffer, buf, count)) {
+               err = -EFAULT;
+               goto out;
+       }
+
+       err = kstrtoint(strstrip(buffer), 0, &oom_adj);
+       if (err)
+               goto out;
+       if ((oom_adj < OOM_ADJUST_MIN || oom_adj > OOM_ADJUST_MAX) &&
+            oom_adj != OOM_DISABLE) {
+               err = -EINVAL;
+               goto out;
+       }
+
+       task = get_proc_task(file->f_path.dentry->d_inode);
+       if (!task) {
+               err = -ESRCH;
+               goto out;
+       }
+
+       task_lock(task);
+       if (!task->mm) {
+               err = -EINVAL;
+               goto err_task_lock;
+       }
+
+       if (!lock_task_sighand(task, &flags)) {
+               err = -ESRCH;
+               goto err_task_lock;
+       }
+
+       /*
+        * Scale /proc/pid/oom_score_adj appropriately ensuring that a maximum
+        * value is always attainable.
+        */
+       if (oom_adj == OOM_ADJUST_MAX)
+               oom_adj = OOM_SCORE_ADJ_MAX;
+       else
+               oom_adj = (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE;
+
+       if (oom_adj < task->signal->oom_score_adj &&
+           !capable(CAP_SYS_RESOURCE)) {
+               err = -EACCES;
+               goto err_sighand;
+       }
+
+       /*
+        * /proc/pid/oom_adj is provided for legacy purposes, ask users to use
+        * /proc/pid/oom_score_adj instead.
+        */
+       printk_once(KERN_WARNING "%s (%d): /proc/%d/oom_adj is deprecated, please use /proc/%d/oom_score_adj instead.\n",
+                 current->comm, task_pid_nr(current), task_pid_nr(task),
+                 task_pid_nr(task));
+
+       task->signal->oom_score_adj = oom_adj;
+       trace_oom_score_adj_update(task);
+err_sighand:
+       unlock_task_sighand(task, &flags);
+err_task_lock:
+       task_unlock(task);
+       put_task_struct(task);
+out:
+       return err < 0 ? err : count;
+}
+
+static const struct file_operations proc_oom_adj_operations = {
+       .read           = oom_adj_read,
+       .write          = oom_adj_write,
+       .llseek         = generic_file_llseek,
+};
+
 static ssize_t oom_score_adj_read(struct file *file, char __user *buf,
                                        size_t count, loff_t *ppos)
 {
@@ -1770,8 +1877,9 @@ static struct dentry *proc_map_files_lookup(struct inode *dir,
        if (!vma)
                goto out_no_vma;
 
-       result = proc_map_files_instantiate(dir, dentry, task,
-                       (void *)(unsigned long)vma->vm_file->f_mode);
+       if (vma->vm_file)
+               result = proc_map_files_instantiate(dir, dentry, task,
+                               (void *)(unsigned long)vma->vm_file->f_mode);
 
 out_no_vma:
        up_read(&mm->mmap_sem);
@@ -2598,6 +2706,7 @@ static const struct pid_entry tgid_base_stuff[] = {
        REG("cgroup",  S_IRUGO, proc_cgroup_operations),
 #endif
        INF("oom_score",  S_IRUGO, proc_oom_score),
+       REG("oom_adj",    S_IRUGO|S_IWUSR, proc_oom_adj_operations),
        REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations),
 #ifdef CONFIG_AUDITSYSCALL
        REG("loginuid",   S_IWUSR|S_IRUGO, proc_loginuid_operations),
@@ -2964,6 +3073,7 @@ static const struct pid_entry tid_base_stuff[] = {
        REG("cgroup",  S_IRUGO, proc_cgroup_operations),
 #endif
        INF("oom_score", S_IRUGO, proc_oom_score),
+       REG("oom_adj",   S_IRUGO|S_IWUSR, proc_oom_adj_operations),
        REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations),
 #ifdef CONFIG_AUDITSYSCALL
        REG("loginuid",  S_IWUSR|S_IRUGO, proc_loginuid_operations),
index cceaab0..43973b0 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 64c3b31..e296572 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 79827ce..90c63f9 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);
@@ -1158,6 +1204,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
        struct vm_area_struct *vma = v;
        struct numa_maps *md = &numa_priv->md;
        struct file *file = vma->vm_file;
+       struct task_struct *task = proc_priv->task;
        struct mm_struct *mm = vma->vm_mm;
        struct mm_walk walk = {};
        struct mempolicy *pol;
@@ -1177,7 +1224,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
        walk.private = md;
        walk.mm = mm;
 
-       pol = get_vma_policy(proc_priv->task, vma, vma->vm_start);
+       pol = get_vma_policy(task, vma, vma->vm_start);
        mpol_to_str(buffer, sizeof(buffer), pol, 0);
        mpol_cond_put(pol);
 
@@ -1189,7 +1236,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
        } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {
                seq_printf(m, " heap");
        } else {
-               pid_t tid = vm_is_stack(proc_priv->task, vma, is_pid);
+               pid_t tid = vm_is_stack(task, vma, is_pid);
                if (tid != 0) {
                        /*
                         * Thread stack in /proc/PID/task/TID/maps or
index a40da07..947fbe0 100644 (file)
@@ -161,6 +161,7 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c)
 
        while (s < e) {
                unsigned long flags;
+               u64 id;
 
                if (c > psinfo->bufsize)
                        c = psinfo->bufsize;
@@ -172,7 +173,7 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c)
                        spin_lock_irqsave(&psinfo->buf_lock, flags);
                }
                memcpy(psinfo->buf, s, c);
-               psinfo->write(PSTORE_TYPE_CONSOLE, 0, NULL, 0, c, psinfo);
+               psinfo->write(PSTORE_TYPE_CONSOLE, 0, &id, 0, c, psinfo);
                spin_unlock_irqrestore(&psinfo->buf_lock, flags);
                s += c;
                c = e - s;
index 557a9c2..05ae3c9 100644 (file)
@@ -1160,6 +1160,8 @@ static int need_print_warning(struct dquot_warn *warn)
                        return uid_eq(current_fsuid(), warn->w_dq_id.uid);
                case GRPQUOTA:
                        return in_group_p(warn->w_dq_id.gid);
+               case PRJQUOTA:  /* Never taken... Just make gcc happy */
+                       return 0;
        }
        return 0;
 }
index f27f01a..d83736f 100644 (file)
@@ -1782,8 +1782,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
 
        BUG_ON(!th->t_trans_id);
 
-       dquot_initialize(inode);
+       reiserfs_write_unlock(inode->i_sb);
        err = dquot_alloc_inode(inode);
+       reiserfs_write_lock(inode->i_sb);
        if (err)
                goto out_end_trans;
        if (!dir->i_nlink) {
@@ -1979,8 +1980,10 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
 
       out_end_trans:
        journal_end(th, th->t_super, th->t_blocks_allocated);
+       reiserfs_write_unlock(inode->i_sb);
        /* Drop can be outside and it needs more credits so it's better to have it outside */
        dquot_drop(inode);
+       reiserfs_write_lock(inode->i_sb);
        inode->i_flags |= S_NOQUOTA;
        make_bad_inode(inode);
 
@@ -3103,10 +3106,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
        /* must be turned off for recursive notify_change calls */
        ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID);
 
-       depth = reiserfs_write_lock_once(inode->i_sb);
        if (is_quota_modification(inode, attr))
                dquot_initialize(inode);
-
+       depth = reiserfs_write_lock_once(inode->i_sb);
        if (attr->ia_valid & ATTR_SIZE) {
                /* version 2 items will be caught by the s_maxbytes check
                 ** done for us in vmtruncate
@@ -3170,7 +3172,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
                error = journal_begin(&th, inode->i_sb, jbegin_count);
                if (error)
                        goto out;
+               reiserfs_write_unlock_once(inode->i_sb, depth);
                error = dquot_transfer(inode, attr);
+               depth = reiserfs_write_lock_once(inode->i_sb);
                if (error) {
                        journal_end(&th, inode->i_sb, jbegin_count);
                        goto out;
index f8afa4b..2f40a4c 100644 (file)
@@ -1968,7 +1968,9 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree
                       key2type(&(key->on_disk_key)));
 #endif
 
+       reiserfs_write_unlock(inode->i_sb);
        retval = dquot_alloc_space_nodirty(inode, pasted_size);
+       reiserfs_write_lock(inode->i_sb);
        if (retval) {
                pathrelse(search_path);
                return retval;
@@ -2061,9 +2063,11 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th,
                               "reiserquota insert_item(): allocating %u id=%u type=%c",
                               quota_bytes, inode->i_uid, head2type(ih));
 #endif
+               reiserfs_write_unlock(inode->i_sb);
                /* We can't dirty inode here. It would be immediately written but
                 * appropriate stat item isn't inserted yet... */
                retval = dquot_alloc_space_nodirty(inode, quota_bytes);
+               reiserfs_write_lock(inode->i_sb);
                if (retval) {
                        pathrelse(path);
                        return retval;
index 1078ae1..418bdc3 100644 (file)
@@ -298,7 +298,9 @@ static int finish_unfinished(struct super_block *s)
                        retval = remove_save_link_only(s, &save_link_key, 0);
                        continue;
                }
+               reiserfs_write_unlock(s);
                dquot_initialize(inode);
+               reiserfs_write_lock(s);
 
                if (truncate && S_ISDIR(inode->i_mode)) {
                        /* We got a truncate request for a dir which is impossible.
@@ -1335,7 +1337,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
                                kfree(qf_names[i]);
 #endif
                err = -EINVAL;
-               goto out_err;
+               goto out_unlock;
        }
 #ifdef CONFIG_QUOTA
        handle_quota_files(s, qf_names, &qfmt);
@@ -1379,7 +1381,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
        if (blocks) {
                err = reiserfs_resize(s, blocks);
                if (err != 0)
-                       goto out_err;
+                       goto out_unlock;
        }
 
        if (*mount_flags & MS_RDONLY) {
@@ -1389,9 +1391,15 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
                        /* it is read-only already */
                        goto out_ok;
 
+               /*
+                * Drop write lock. Quota will retake it when needed and lock
+                * ordering requires calling dquot_suspend() without it.
+                */
+               reiserfs_write_unlock(s);
                err = dquot_suspend(s, -1);
                if (err < 0)
                        goto out_err;
+               reiserfs_write_lock(s);
 
                /* try to remount file system with read-only permissions */
                if (sb_umount_state(rs) == REISERFS_VALID_FS
@@ -1401,7 +1409,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
 
                err = journal_begin(&th, s, 10);
                if (err)
-                       goto out_err;
+                       goto out_unlock;
 
                /* Mounting a rw partition read-only. */
                reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
@@ -1416,7 +1424,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
 
                if (reiserfs_is_journal_aborted(journal)) {
                        err = journal->j_errno;
-                       goto out_err;
+                       goto out_unlock;
                }
 
                handle_data_mode(s, mount_options);
@@ -1425,7 +1433,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
                s->s_flags &= ~MS_RDONLY;       /* now it is safe to call journal_begin */
                err = journal_begin(&th, s, 10);
                if (err)
-                       goto out_err;
+                       goto out_unlock;
 
                /* Mount a partition which is read-only, read-write */
                reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
@@ -1442,10 +1450,16 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
        SB_JOURNAL(s)->j_must_wait = 1;
        err = journal_end(&th, s, 10);
        if (err)
-               goto out_err;
+               goto out_unlock;
 
        if (!(*mount_flags & MS_RDONLY)) {
+               /*
+                * Drop write lock. Quota will retake it when needed and lock
+                * ordering requires calling dquot_resume() without it.
+                */
+               reiserfs_write_unlock(s);
                dquot_resume(s, -1);
+               reiserfs_write_lock(s);
                finish_unfinished(s);
                reiserfs_xattr_init(s, *mount_flags);
        }
@@ -1455,9 +1469,10 @@ out_ok:
        reiserfs_write_unlock(s);
        return 0;
 
+out_unlock:
+       reiserfs_write_unlock(s);
 out_err:
        kfree(new_opts);
-       reiserfs_write_unlock(s);
        return err;
 }
 
@@ -2095,13 +2110,15 @@ static int reiserfs_write_dquot(struct dquot *dquot)
                          REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
        if (ret)
                goto out;
+       reiserfs_write_unlock(dquot->dq_sb);
        ret = dquot_commit(dquot);
+       reiserfs_write_lock(dquot->dq_sb);
        err =
            journal_end(&th, dquot->dq_sb,
                        REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
        if (!ret && err)
                ret = err;
-      out:
+out:
        reiserfs_write_unlock(dquot->dq_sb);
        return ret;
 }
@@ -2117,13 +2134,15 @@ static int reiserfs_acquire_dquot(struct dquot *dquot)
                          REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
        if (ret)
                goto out;
+       reiserfs_write_unlock(dquot->dq_sb);
        ret = dquot_acquire(dquot);
+       reiserfs_write_lock(dquot->dq_sb);
        err =
            journal_end(&th, dquot->dq_sb,
                        REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
        if (!ret && err)
                ret = err;
-      out:
+out:
        reiserfs_write_unlock(dquot->dq_sb);
        return ret;
 }
@@ -2137,19 +2156,21 @@ static int reiserfs_release_dquot(struct dquot *dquot)
        ret =
            journal_begin(&th, dquot->dq_sb,
                          REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
+       reiserfs_write_unlock(dquot->dq_sb);
        if (ret) {
                /* Release dquot anyway to avoid endless cycle in dqput() */
                dquot_release(dquot);
                goto out;
        }
        ret = dquot_release(dquot);
+       reiserfs_write_lock(dquot->dq_sb);
        err =
            journal_end(&th, dquot->dq_sb,
                        REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
        if (!ret && err)
                ret = err;
-      out:
        reiserfs_write_unlock(dquot->dq_sb);
+out:
        return ret;
 }
 
@@ -2174,11 +2195,13 @@ static int reiserfs_write_info(struct super_block *sb, int type)
        ret = journal_begin(&th, sb, 2);
        if (ret)
                goto out;
+       reiserfs_write_unlock(sb);
        ret = dquot_commit_info(sb, type);
+       reiserfs_write_lock(sb);
        err = journal_end(&th, sb, 2);
        if (!ret && err)
                ret = err;
-      out:
+out:
        reiserfs_write_unlock(sb);
        return ret;
 }
@@ -2203,8 +2226,11 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
        struct reiserfs_transaction_handle th;
        int opt = type == USRQUOTA ? REISERFS_USRQUOTA : REISERFS_GRPQUOTA;
 
-       if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt)))
-               return -EINVAL;
+       reiserfs_write_lock(sb);
+       if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) {
+               err = -EINVAL;
+               goto out;
+       }
 
        /* Quotafile not on the same filesystem? */
        if (path->dentry->d_sb != sb) {
@@ -2246,8 +2272,10 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
                if (err)
                        goto out;
        }
-       err = dquot_quota_on(sb, type, format_id, path);
+       reiserfs_write_unlock(sb);
+       return dquot_quota_on(sb, type, format_id, path);
 out:
+       reiserfs_write_unlock(sb);
        return err;
 }
 
@@ -2320,7 +2348,9 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
                tocopy = sb->s_blocksize - offset < towrite ?
                    sb->s_blocksize - offset : towrite;
                tmp_bh.b_state = 0;
+               reiserfs_write_lock(sb);
                err = reiserfs_get_block(inode, blk, &tmp_bh, GET_BLOCK_CREATE);
+               reiserfs_write_unlock(sb);
                if (err)
                        goto out;
                if (offset || tocopy != sb->s_blocksize)
@@ -2336,10 +2366,12 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
                flush_dcache_page(bh->b_page);
                set_buffer_uptodate(bh);
                unlock_buffer(bh);
+               reiserfs_write_lock(sb);
                reiserfs_prepare_for_journal(sb, bh, 1);
                journal_mark_dirty(current->journal_info, sb, bh);
                if (!journal_quota)
                        reiserfs_add_ordered_list(inode, bh);
+               reiserfs_write_unlock(sb);
                brelse(bh);
                offset = 0;
                towrite -= tocopy;
index 6b0bb00..2fbdff6 100644 (file)
@@ -485,20 +485,18 @@ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
 /**
  *     sysfs_pathname - return full path to sysfs dirent
  *     @sd: sysfs_dirent whose path we want
- *     @path: caller allocated buffer
+ *     @path: caller allocated buffer of size PATH_MAX
  *
  *     Gives the name "/" to the sysfs_root entry; any path returned
  *     is relative to wherever sysfs is mounted.
- *
- *     XXX: does no error checking on @path size
  */
 static char *sysfs_pathname(struct sysfs_dirent *sd, char *path)
 {
        if (sd->s_parent) {
                sysfs_pathname(sd->s_parent, path);
-               strcat(path, "/");
+               strlcat(path, "/", PATH_MAX);
        }
-       strcat(path, sd->s_name);
+       strlcat(path, sd->s_name, PATH_MAX);
        return path;
 }
 
@@ -531,9 +529,11 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
                char *path = kzalloc(PATH_MAX, GFP_KERNEL);
                WARN(1, KERN_WARNING
                     "sysfs: cannot create duplicate filename '%s'\n",
-                    (path == NULL) ? sd->s_name :
-                    strcat(strcat(sysfs_pathname(acxt->parent_sd, path), "/"),
-                           sd->s_name));
+                    (path == NULL) ? sd->s_name
+                                   : (sysfs_pathname(acxt->parent_sd, path),
+                                      strlcat(path, "/", PATH_MAX),
+                                      strlcat(path, sd->s_name, PATH_MAX),
+                                      path));
                kfree(path);
        }
 
index 28ec13a..2dcf3d4 100644 (file)
@@ -681,8 +681,16 @@ 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) {
+                       /*
+                        * The first condition means the following: go scan the
+                        * LPT if there are uncategorized lprops, which means
+                        * there may be freeable LEBs there (UBIFS does not
+                        * store the information about freeable LEBs in the
+                        * master node).
+                        */
+                       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 e5a2a35..46190a7 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 5486346..d133c27 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 e164ddd..e21c119 100644 (file)
@@ -846,7 +846,7 @@ static int __simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
                              const void *value, size_t size, int flags)
 {
        struct simple_xattr *xattr;
-       struct simple_xattr *uninitialized_var(new_xattr);
+       struct simple_xattr *new_xattr = NULL;
        int err = 0;
 
        /* value == NULL means remove */
index 4f33c32..335206a 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 93be4a6..feacb06 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 f1647ca..f7876c6 100644 (file)
@@ -121,6 +121,8 @@ xfs_allocbt_free_block(
        xfs_extent_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1,
                              XFS_EXTENT_BUSY_SKIP_DISCARD);
        xfs_trans_agbtree_delta(cur->bc_tp, -1);
+
+       xfs_trans_binval(cur->bc_tp, bp);
        return 0;
 }
 
index e562dd4..e57e2da 100644 (file)
@@ -481,11 +481,17 @@ static inline int bio_add_buffer(struct bio *bio, struct buffer_head *bh)
  *
  * The fix is two passes across the ioend list - one to start writeback on the
  * buffer_heads, and then submit them for I/O on the second pass.
+ *
+ * If @fail is non-zero, it means that we have a situation where some part of
+ * the submission process has failed after we have marked paged for writeback
+ * and unlocked them. In this situation, we need to fail the ioend chain rather
+ * than submit it to IO. This typically only happens on a filesystem shutdown.
  */
 STATIC void
 xfs_submit_ioend(
        struct writeback_control *wbc,
-       xfs_ioend_t             *ioend)
+       xfs_ioend_t             *ioend,
+       int                     fail)
 {
        xfs_ioend_t             *head = ioend;
        xfs_ioend_t             *next;
@@ -506,6 +512,18 @@ xfs_submit_ioend(
                next = ioend->io_list;
                bio = NULL;
 
+               /*
+                * If we are failing the IO now, just mark the ioend with an
+                * error and finish it. This will run IO completion immediately
+                * as there is only one reference to the ioend at this point in
+                * time.
+                */
+               if (fail) {
+                       ioend->io_error = -fail;
+                       xfs_finish_ioend(ioend);
+                       continue;
+               }
+
                for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) {
 
                        if (!bio) {
@@ -1060,7 +1078,18 @@ xfs_vm_writepage(
 
        xfs_start_page_writeback(page, 1, count);
 
-       if (ioend && imap_valid) {
+       /* if there is no IO to be submitted for this page, we are done */
+       if (!ioend)
+               return 0;
+
+       ASSERT(iohead);
+
+       /*
+        * Any errors from this point onwards need tobe reported through the IO
+        * completion path as we have marked the initial page as under writeback
+        * and unlocked it.
+        */
+       if (imap_valid) {
                xfs_off_t               end_index;
 
                end_index = imap.br_startoff + imap.br_blockcount;
@@ -1079,20 +1108,15 @@ xfs_vm_writepage(
                                  wbc, end_index);
        }
 
-       if (iohead) {
-               /*
-                * Reserve log space if we might write beyond the on-disk
-                * inode size.
-                */
-               if (ioend->io_type != XFS_IO_UNWRITTEN &&
-                   xfs_ioend_is_append(ioend)) {
-                       err = xfs_setfilesize_trans_alloc(ioend);
-                       if (err)
-                               goto error;
-               }
 
-               xfs_submit_ioend(wbc, iohead);
-       }
+       /*
+        * Reserve log space if we might write beyond the on-disk inode size.
+        */
+       err = 0;
+       if (ioend->io_type != XFS_IO_UNWRITTEN && xfs_ioend_is_append(ioend))
+               err = xfs_setfilesize_trans_alloc(ioend);
+
+       xfs_submit_ioend(wbc, iohead, err);
 
        return 0;
 
index d330111..70eec18 100644 (file)
@@ -1291,6 +1291,7 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
        leaf2 = blk2->bp->b_addr;
        ASSERT(leaf1->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
        ASSERT(leaf2->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
+       ASSERT(leaf2->hdr.count == 0);
        args = state->args;
 
        trace_xfs_attr_leaf_rebalance(args);
@@ -1361,6 +1362,7 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
                 * I assert that since all callers pass in an empty
                 * second buffer, this code should never execute.
                 */
+               ASSERT(0);
 
                /*
                 * Figure the total bytes to be added to the destination leaf.
@@ -1422,10 +1424,24 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
                        args->index2 = 0;
                        args->blkno2 = blk2->blkno;
                } else {
+                       /*
+                        * On a double leaf split, the original attr location
+                        * is already stored in blkno2/index2, so don't
+                        * overwrite it overwise we corrupt the tree.
+                        */
                        blk2->index = blk1->index
                                    - be16_to_cpu(leaf1->hdr.count);
-                       args->index = args->index2 = blk2->index;
-                       args->blkno = args->blkno2 = blk2->blkno;
+                       args->index = blk2->index;
+                       args->blkno = blk2->blkno;
+                       if (!state->extravalid) {
+                               /*
+                                * set the new attr location to match the old
+                                * one and let the higher level split code
+                                * decide where in the leaf to place it.
+                                */
+                               args->index2 = blk2->index;
+                               args->blkno2 = blk2->blkno;
+                       }
                }
        } else {
                ASSERT(state->inleaf == 1);
index 848ffa7..83d0cf3 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 803b56d..5f469c3 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 933b793..4b0b8dd 100644 (file)
@@ -1197,9 +1197,14 @@ xfs_buf_bio_end_io(
 {
        xfs_buf_t               *bp = (xfs_buf_t *)bio->bi_private;
 
-       xfs_buf_ioerror(bp, -error);
+       /*
+        * don't overwrite existing errors - otherwise we can lose errors on
+        * buffers that require multiple bios to complete.
+        */
+       if (!bp->b_error)
+               xfs_buf_ioerror(bp, -error);
 
-       if (!error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ))
+       if (!bp->b_error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ))
                invalidate_kernel_vmap_range(bp->b_addr, xfs_buf_vmap_len(bp));
 
        _xfs_buf_ioend(bp, 1);
@@ -1279,6 +1284,11 @@ next_chunk:
                if (size)
                        goto next_chunk;
        } else {
+               /*
+                * This is guaranteed not to be the last io reference count
+                * because the caller (xfs_buf_iorequest) holds a count itself.
+                */
+               atomic_dec(&bp->b_io_remaining);
                xfs_buf_ioerror(bp, EIO);
                bio_put(bio);
        }
index a8d0ed9..becf4a9 100644 (file)
@@ -526,7 +526,25 @@ xfs_buf_item_unpin(
                }
                xfs_buf_relse(bp);
        } else if (freed && remove) {
+               /*
+                * There are currently two references to the buffer - the active
+                * LRU reference and the buf log item. What we are about to do
+                * here - simulate a failed IO completion - requires 3
+                * references.
+                *
+                * The LRU reference is removed by the xfs_buf_stale() call. The
+                * buf item reference is removed by the xfs_buf_iodone()
+                * callback that is run by xfs_buf_do_callbacks() during ioend
+                * processing (via the bp->b_iodone callback), and then finally
+                * the ioend processing will drop the IO reference if the buffer
+                * is marked XBF_ASYNC.
+                *
+                * Hence we need to take an additional reference here so that IO
+                * completion processing doesn't free the buffer prematurely.
+                */
                xfs_buf_lock(bp);
+               xfs_buf_hold(bp);
+               bp->b_flags |= XBF_ASYNC;
                xfs_buf_ioerror(bp, EIO);
                XFS_BUF_UNDONE(bp);
                xfs_buf_stale(bp);
index c25b094..4beaede 100644 (file)
@@ -399,9 +399,26 @@ xfs_growfs_data_private(
 
        /* update secondary superblocks. */
        for (agno = 1; agno < nagcount; agno++) {
-               error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp,
+               error = 0;
+               /*
+                * new secondary superblocks need to be zeroed, not read from
+                * disk as the contents of the new area we are growing into is
+                * completely unknown.
+                */
+               if (agno < oagcount) {
+                       error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp,
                                  XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)),
                                  XFS_FSS_TO_BB(mp, 1), 0, &bp);
+               } else {
+                       bp = xfs_trans_get_buf(NULL, mp->m_ddev_targp,
+                                 XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)),
+                                 XFS_FSS_TO_BB(mp, 1), 0);
+                       if (bp)
+                               xfs_buf_zero(bp, 0, BBTOB(bp->b_length));
+                       else
+                               error = ENOMEM;
+               }
+
                if (error) {
                        xfs_warn(mp,
                "error %d reading secondary superblock for ag %d",
@@ -423,7 +440,7 @@ xfs_growfs_data_private(
                        break; /* no point in continuing */
                }
        }
-       return 0;
+       return error;
 
  error0:
        xfs_trans_cancel(tp, XFS_TRANS_ABORT);
index 445bf1a..c5c4ef4 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;
 
index 2778258..1938b41 100644 (file)
@@ -1509,7 +1509,8 @@ xfs_ifree_cluster(
                 * to mark all the active inodes on the buffer stale.
                 */
                bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, blkno,
-                                       mp->m_bsize * blks_per_cluster, 0);
+                                       mp->m_bsize * blks_per_cluster,
+                                       XBF_UNMAPPED);
 
                if (!bp)
                        return ENOMEM;
index 8305f2a..c1df3c6 100644 (file)
@@ -70,7 +70,7 @@ xfs_find_handle(
        int                     hsize;
        xfs_handle_t            handle;
        struct inode            *inode;
-       struct fd               f;
+       struct fd               f = {0};
        struct path             path;
        int                     error;
        struct xfs_inode        *ip;
index 973dff6..7f53766 100644 (file)
@@ -584,7 +584,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 7f4f937..4dad756 100644 (file)
@@ -2387,14 +2387,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++;
index 5da3ace..d308749 100644 (file)
@@ -3541,7 +3541,7 @@ xlog_do_recovery_pass(
                                 *   - order is important.
                                 */
                                error = xlog_bread_offset(log, 0,
-                                               bblks - split_bblks, hbp,
+                                               bblks - split_bblks, dbp,
                                                offset + BBTOB(split_bblks));
                                if (error)
                                        goto bread_err2;
index 8d226bf..83256b6 100644 (file)
@@ -1,12 +1,8 @@
 # Top-level Makefile calls into asm-$(ARCH)
 # List only non-arch directories below
 
-header-y += asm-generic/
 header-y += linux/
 header-y += sound/
-header-y += mtd/
 header-y += rdma/
 header-y += video/
-header-y += drm/
-header-y += xen/
 header-y += scsi/
index 03f1485..0943457 100644 (file)
  *****************************************************************************/
 
 #define ACPI_DEBUGGER_MAX_ARGS          8      /* Must be max method args + 1 */
+#define ACPI_DB_LINE_BUFFER_SIZE       512
 
 #define ACPI_DEBUGGER_COMMAND_PROMPT    '-'
 #define ACPI_DEBUGGER_EXECUTE_PROMPT    '%'
index 1950344..6c3890e 100644 (file)
 #define AE_CODE_TBL_MAX                 0x0005
 
 /*
- * AML exceptions.  These are caused by problems with
+ * AML exceptions. These are caused by problems with
  * the actual AML byte stream
  */
 #define AE_AML_BAD_OPCODE               (acpi_status) (0x0001 | AE_CODE_AML)
index 745dd24..7665df6 100644 (file)
@@ -50,6 +50,7 @@
 #define METHOD_NAME__HID        "_HID"
 #define METHOD_NAME__CID        "_CID"
 #define METHOD_NAME__UID        "_UID"
+#define METHOD_NAME__SUB        "_SUB"
 #define METHOD_NAME__ADR        "_ADR"
 #define METHOD_NAME__INI        "_INI"
 #define METHOD_NAME__STA        "_STA"
index 0daa0fb..7ced5dc 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 */
@@ -180,6 +179,7 @@ struct acpi_device_pnp {
        acpi_device_name device_name;   /* Driver-determined */
        acpi_device_class device_class; /*        "          */
        union acpi_object *str_obj;     /* unicode string for _STR method */
+       unsigned long sun;              /* _SUN */
 };
 
 #define acpi_device_bid(d)     ((d)->pnp.bus_id)
@@ -201,6 +201,7 @@ struct acpi_device_power_flags {
 struct acpi_device_power_state {
        struct {
                u8 valid:1;
+               u8 os_accessible:1;
                u8 explicit_set:1;      /* _PSx present? */
                u8 reserved:6;
        } flags;
@@ -339,6 +340,7 @@ acpi_status acpi_bus_get_status_handle(acpi_handle handle,
                                       unsigned long long *sta);
 int acpi_bus_get_status(struct acpi_device *device);
 int acpi_bus_set_power(acpi_handle handle, int state);
+int acpi_device_set_power(struct acpi_device *device, int state);
 int acpi_bus_update_power(acpi_handle handle, int *state_p);
 bool acpi_bus_power_manageable(acpi_handle handle);
 bool acpi_bus_can_wakeup(acpi_handle handle);
@@ -410,36 +412,100 @@ acpi_handle acpi_get_child(acpi_handle, u64);
 int acpi_is_root_bridge(acpi_handle);
 acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int);
 struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle);
-#define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle))
+#define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)ACPI_HANDLE(dev))
 
 int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state);
 int acpi_disable_wakeup_device_power(struct acpi_device *dev);
 
 #ifdef CONFIG_PM
+acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
+                                acpi_notify_handler handler, void *context);
+acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
+                                   acpi_notify_handler handler);
+int acpi_device_power_state(struct device *dev, struct acpi_device *adev,
+                           u32 target_state, int d_max_in, int *d_min_p);
 int acpi_pm_device_sleep_state(struct device *, int *, int);
 #else
-static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m)
+static inline acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
+                                              acpi_notify_handler handler,
+                                              void *context)
+{
+       return AE_SUPPORT;
+}
+static inline acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
+                                                 acpi_notify_handler handler)
+{
+       return AE_SUPPORT;
+}
+static inline int __acpi_device_power_state(int m, int *p)
 {
        if (p)
                *p = ACPI_STATE_D0;
        return (m >= ACPI_STATE_D0 && m <= ACPI_STATE_D3) ? m : ACPI_STATE_D0;
 }
+static inline int acpi_device_power_state(struct device *dev,
+                                         struct acpi_device *adev,
+                                         u32 target_state, int d_max_in,
+                                         int *d_min_p)
+{
+       return __acpi_device_power_state(d_max_in, d_min_p);
+}
+static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m)
+{
+       return __acpi_device_power_state(m, p);
+}
 #endif
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM_RUNTIME
+int __acpi_device_run_wake(struct acpi_device *, bool);
 int acpi_pm_device_run_wake(struct device *, bool);
-int acpi_pm_device_sleep_wake(struct device *, bool);
 #else
+static inline int __acpi_device_run_wake(struct acpi_device *adev, bool en)
+{
+       return -ENODEV;
+}
 static inline int acpi_pm_device_run_wake(struct device *dev, bool enable)
 {
        return -ENODEV;
 }
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+int __acpi_device_sleep_wake(struct acpi_device *, u32, bool);
+int acpi_pm_device_sleep_wake(struct device *, bool);
+#else
+static inline int __acpi_device_sleep_wake(struct acpi_device *adev,
+                                          u32 target_state, bool enable)
+{
+       return -ENODEV;
+}
 static inline int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
 {
        return -ENODEV;
 }
 #endif
 
+#ifdef CONFIG_ACPI_SLEEP
+u32 acpi_target_system_state(void);
+#else
+static inline u32 acpi_target_system_state(void) { return ACPI_STATE_S0; }
+#endif
+
+static inline bool acpi_device_power_manageable(struct acpi_device *adev)
+{
+       return adev->flags.power_manageable;
+}
+
+static inline bool acpi_device_can_wakeup(struct acpi_device *adev)
+{
+       return adev->wakeup.flags.valid;
+}
+
+static inline bool acpi_device_can_poweroff(struct acpi_device *adev)
+{
+       return adev->power.states[ACPI_STATE_D3_COLD].flags.os_accessible;
+}
+
 #else  /* CONFIG_ACPI */
 
 static inline int register_acpi_bus_type(void *bus) { return 0; }
index 1222ba9..4315274 100644 (file)
@@ -1,7 +1,6 @@
-
 /******************************************************************************
  *
- * Name: acpiosxf.h - All interfaces to the OS Services Layer (OSL).  These
+ * Name: acpiosxf.h - All interfaces to the OS Services Layer (OSL). These
  *                    interfaces must be implemented by OSL to interface the
  *                    ACPI components to the host operating system.
  *
index 8b891db..3d88395 100644 (file)
@@ -1,4 +1,3 @@
-
 /******************************************************************************
  *
  * Name: acpixf.h - External interfaces to the ACPI subsystem
@@ -47,7 +46,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20120913
+#define ACPI_CA_VERSION                 0x20121018
 
 #include <acpi/acconfig.h>
 #include <acpi/actypes.h>
@@ -178,8 +177,7 @@ acpi_status acpi_unload_table_id(acpi_owner_id id);
 
 acpi_status
 acpi_get_table_header(acpi_string signature,
-                     u32 instance,
-                     struct acpi_table_header *out_table_header);
+                     u32 instance, struct acpi_table_header *out_table_header);
 
 acpi_status
 acpi_get_table_with_size(acpi_string signature,
@@ -190,8 +188,7 @@ acpi_get_table(acpi_string signature,
               u32 instance, struct acpi_table_header **out_table);
 
 acpi_status
-acpi_get_table_by_index(u32 table_index,
-                       struct acpi_table_header **out_table);
+acpi_get_table_by_index(u32 table_index, struct acpi_table_header **out_table);
 
 acpi_status
 acpi_install_table_handler(acpi_tbl_handler handler, void *context);
@@ -274,7 +271,7 @@ acpi_install_initialization_handler(acpi_init_handler handler, u32 function);
 
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
                                acpi_install_global_event_handler
-                               (ACPI_GBL_EVENT_HANDLER handler, void *context))
+                               (acpi_gbl_event_handler handler, void *context))
 
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
                                 acpi_install_fixed_event_handler(u32
@@ -300,10 +297,9 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
                                                         u32 gpe_number,
                                                         acpi_gpe_handler
                                                         address))
-acpi_status
-acpi_install_notify_handler(acpi_handle device,
-                           u32 handler_type,
-                           acpi_notify_handler handler, void *context);
+acpi_status acpi_install_notify_handler(acpi_handle device, u32 handler_type,
+                                       acpi_notify_handler handler,
+                                       void *context);
 
 acpi_status
 acpi_remove_notify_handler(acpi_handle device,
index 8c61b5f..6585141 100644 (file)
@@ -277,10 +277,10 @@ struct acpi_table_gtdt {
  ******************************************************************************/
 
 #define ACPI_MPST_CHANNEL_INFO \
-       u16                             reserved1; \
        u8                              channel_id; \
-       u8                              reserved2; \
-       u16                             power_node_count;
+       u8                              reserved1[3]; \
+       u16                             power_node_count; \
+       u16                             reserved2;
 
 /* Main table */
 
@@ -304,9 +304,8 @@ struct acpi_mpst_power_node {
        u32 length;
        u64 range_address;
        u64 range_length;
-       u8 num_power_states;
-       u8 num_physical_components;
-       u16 reserved2;
+       u32 num_power_states;
+       u32 num_physical_components;
 };
 
 /* Values for Flags field above */
@@ -332,10 +331,11 @@ struct acpi_mpst_component {
 
 struct acpi_mpst_data_hdr {
        u16 characteristics_count;
+       u16 reserved;
 };
 
 struct acpi_mpst_power_data {
-       u8 revision;
+       u8 structure_id;
        u8 flags;
        u16 reserved1;
        u32 average_power;
@@ -356,10 +356,10 @@ struct acpi_mpst_shared {
        u32 signature;
        u16 pcc_command;
        u16 pcc_status;
-       u16 command_register;
-       u16 status_register;
-       u16 power_state_id;
-       u16 power_node_id;
+       u32 command_register;
+       u32 status_register;
+       u32 power_state_id;
+       u32 power_node_id;
        u64 energy_consumed;
        u64 average_power;
 };
index a85bae9..4f43f1f 100644 (file)
@@ -453,10 +453,14 @@ typedef u64 acpi_integer;
 #define ACPI_PHYSADDR_TO_PTR(i)         ACPI_TO_POINTER(i)
 #define ACPI_PTR_TO_PHYSADDR(i)         ACPI_TO_INTEGER(i)
 
+/* Optimizations for 4-character (32-bit) acpi_name manipulation */
+
 #ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED
 #define ACPI_COMPARE_NAME(a,b)          (*ACPI_CAST_PTR (u32, (a)) == *ACPI_CAST_PTR (u32, (b)))
+#define ACPI_MOVE_NAME(dest,src)        (*ACPI_CAST_PTR (u32, (dest)) = *ACPI_CAST_PTR (u32, (src)))
 #else
 #define ACPI_COMPARE_NAME(a,b)          (!ACPI_STRNCMP (ACPI_CAST_PTR (char, (a)), ACPI_CAST_PTR (char, (b)), ACPI_NAME_SIZE))
+#define ACPI_MOVE_NAME(dest,src)        (ACPI_STRNCPY (ACPI_CAST_PTR (char, (dest)), ACPI_CAST_PTR (char, (src)), ACPI_NAME_SIZE))
 #endif
 
 /*******************************************************************************
@@ -796,11 +800,11 @@ typedef u8 acpi_adr_space_type;
 
 /* Sleep function dispatch */
 
-typedef acpi_status(*ACPI_SLEEP_FUNCTION) (u8 sleep_state);
+typedef acpi_status(*acpi_sleep_function) (u8 sleep_state);
 
 struct acpi_sleep_functions {
-       ACPI_SLEEP_FUNCTION legacy_function;
-       ACPI_SLEEP_FUNCTION extended_function;
+       acpi_sleep_function legacy_function;
+       acpi_sleep_function extended_function;
 };
 
 /*
@@ -922,7 +926,8 @@ struct acpi_system_info {
 /*
  * Types specific to the OS service interfaces
  */
-typedef u32(ACPI_SYSTEM_XFACE * acpi_osd_handler) (void *context);
+typedef u32
+ (ACPI_SYSTEM_XFACE * acpi_osd_handler) (void *context);
 
 typedef void
  (ACPI_SYSTEM_XFACE * acpi_osd_exec_callback) (void *context);
@@ -931,14 +936,15 @@ typedef void
  * Various handlers and callback procedures
  */
 typedef
-void (*ACPI_GBL_EVENT_HANDLER) (u32 event_type,
+void (*acpi_gbl_event_handler) (u32 event_type,
                               acpi_handle device,
                               u32 event_number, void *context);
 
 #define ACPI_EVENT_TYPE_GPE         0
 #define ACPI_EVENT_TYPE_FIXED       1
 
-typedef u32(*acpi_event_handler) (void *context);
+typedef
+u32(*acpi_event_handler) (void *context);
 
 typedef
 u32 (*acpi_gpe_handler) (acpi_handle gpe_device, u32 gpe_number, void *context);
@@ -1018,17 +1024,17 @@ u32 (*acpi_interface_handler) (acpi_string interface_name, u32 supported);
 
 #define ACPI_UUID_LENGTH                16
 
-/* Structures used for device/processor HID, UID, CID */
+/* Structures used for device/processor HID, UID, CID, and SUB */
 
-struct acpica_device_id {
+struct acpi_pnp_device_id {
        u32 length;             /* Length of string + null */
        char *string;
 };
 
-struct acpica_device_id_list {
+struct acpi_pnp_device_id_list {
        u32 count;              /* Number of IDs in Ids array */
        u32 list_size;          /* Size of list, including ID strings */
-       struct acpica_device_id ids[1]; /* ID array */
+       struct acpi_pnp_device_id ids[1];       /* ID array */
 };
 
 /*
@@ -1046,9 +1052,10 @@ struct acpi_device_info {
        u8 lowest_dstates[5];   /* _sx_w values: 0xFF indicates not valid */
        u32 current_status;     /* _STA value */
        u64 address;    /* _ADR value */
-       struct acpica_device_id hardware_id;    /* _HID value */
-       struct acpica_device_id unique_id;      /* _UID value */
-       struct acpica_device_id_list compatible_id_list;        /* _CID list <must be last> */
+       struct acpi_pnp_device_id hardware_id;  /* _HID value */
+       struct acpi_pnp_device_id unique_id;    /* _UID value */
+       struct acpi_pnp_device_id subsystem_id; /* _SUB value */
+       struct acpi_pnp_device_id_list compatible_id_list;      /* _CID list <must be last> */
 };
 
 /* Values for Flags field above (acpi_get_object_info) */
@@ -1061,11 +1068,12 @@ struct acpi_device_info {
 #define ACPI_VALID_ADR                  0x02
 #define ACPI_VALID_HID                  0x04
 #define ACPI_VALID_UID                  0x08
-#define ACPI_VALID_CID                  0x10
-#define ACPI_VALID_SXDS                 0x20
-#define ACPI_VALID_SXWS                 0x40
+#define ACPI_VALID_SUB                  0x10
+#define ACPI_VALID_CID                  0x20
+#define ACPI_VALID_SXDS                 0x40
+#define ACPI_VALID_SXWS                 0x80
 
-/* Flags for _STA method */
+/* Flags for _STA return value (current_status above) */
 
 #define ACPI_STA_DEVICE_PRESENT         0x01
 #define ACPI_STA_DEVICE_ENABLED         0x02
diff --git a/include/asm-generic/Kbuild b/include/asm-generic/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index eb70ca2..20ca766 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/of.h>
+#include <linux/pinctrl/pinctrl.h>
 
 #ifdef CONFIG_GPIOLIB
 
@@ -137,6 +138,15 @@ struct gpio_chip {
        int (*of_xlate)(struct gpio_chip *gc,
                        const struct of_phandle_args *gpiospec, u32 *flags);
 #endif
+#ifdef CONFIG_PINCTRL
+       /*
+        * If CONFIG_PINCTRL is enabled, then gpio controllers can optionally
+        * describe the actual pin range which they serve in an SoC. This
+        * information would be used by pinctrl subsystem to configure
+        * corresponding pins for gpio usage.
+        */
+       struct list_head pin_ranges;
+#endif
 };
 
 extern const char *gpiochip_is_requested(struct gpio_chip *chip,
@@ -260,4 +270,41 @@ static inline void gpio_unexport(unsigned gpio)
 }
 #endif /* CONFIG_GPIO_SYSFS */
 
+#ifdef CONFIG_PINCTRL
+
+/**
+ * struct gpio_pin_range - pin range controlled by a gpio chip
+ * @head: list for maintaining set of pin ranges, used internally
+ * @pctldev: pinctrl device which handles corresponding pins
+ * @range: actual range of pins controlled by a gpio controller
+ */
+
+struct gpio_pin_range {
+       struct list_head node;
+       struct pinctrl_dev *pctldev;
+       struct pinctrl_gpio_range range;
+};
+
+int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
+                          unsigned int gpio_offset, unsigned int pin_offset,
+                          unsigned int npins);
+void gpiochip_remove_pin_ranges(struct gpio_chip *chip);
+
+#else
+
+static inline int
+gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
+                      unsigned int gpio_offset, unsigned int pin_offset,
+                      unsigned int npins)
+{
+       return 0;
+}
+
+static inline void
+gpiochip_remove_pin_ranges(struct gpio_chip *chip)
+{
+}
+
+#endif /* CONFIG_PINCTRL */
+
 #endif /* _ASM_GENERIC_GPIO_H */
diff --git a/include/drm/Kbuild b/include/drm/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index c78bb99..c5c35e6 100644 (file)
        {0x1002, 0x6788, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x678A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6790, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x6791, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x6792, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6798, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6799, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x679A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x679B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x679E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x679F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6810, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x6811, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6816, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6817, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6818, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
index 5b57367..7fe2dae 100644 (file)
@@ -1,31 +1,5 @@
-header-y += byteorder/
-header-y += can/
-header-y += caif/
 header-y += dvb/
 header-y += hdlc/
 header-y += hsi/
-header-y += isdn/
-header-y += mmc/
-header-y += nfsd/
 header-y += raid/
-header-y += spi/
-header-y += sunrpc/
-header-y += tc_act/
-header-y += tc_ematch/
-header-y += netfilter/
-header-y += netfilter_arp/
-header-y += netfilter_bridge/
-header-y += netfilter_ipv4/
-header-y += netfilter_ipv6/
 header-y += usb/
-header-y += wimax/
-
-ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/a.out.h \
-                 $(srctree)/arch/$(SRCARCH)/include/uapi/asm/a.out.h),)
-endif
-ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/kvm.h \
-                 $(srctree)/arch/$(SRCARCH)/include/uapi/asm/kvm.h),)
-endif
-ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/kvm_para.h \
-                 $(srctree)/arch/$(SRCARCH)/include/uapi/asm/kvm_para.h),)
-endif
index 90be989..c33fa3c 100644 (file)
@@ -25,7 +25,9 @@
 #ifndef _LINUX_ACPI_H
 #define _LINUX_ACPI_H
 
+#include <linux/errno.h>
 #include <linux/ioport.h>      /* for struct resource */
+#include <linux/device.h>
 
 #ifdef CONFIG_ACPI
 
@@ -250,6 +252,26 @@ extern int pnpacpi_disabled;
 
 #define PXM_INVAL      (-1)
 
+bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res);
+bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res);
+bool acpi_dev_resource_address_space(struct acpi_resource *ares,
+                                    struct resource *res);
+bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
+                                        struct resource *res);
+unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable);
+bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
+                                struct resource *res);
+
+struct resource_list_entry {
+       struct list_head node;
+       struct resource res;
+};
+
+void acpi_dev_free_resource_list(struct list_head *list);
+int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list,
+                          int (*preproc)(struct acpi_resource *, void *),
+                          void *preproc_data);
+
 int acpi_check_resource_conflict(const struct resource *res);
 
 int acpi_check_region(resource_size_t start, resource_size_t n,
@@ -257,10 +279,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 {
@@ -364,6 +390,17 @@ extern int acpi_nvs_register(__u64 start, __u64 size);
 extern int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *),
                                    void *data);
 
+const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
+                                              const struct device *dev);
+
+static inline bool acpi_driver_match_device(struct device *dev,
+                                           const struct device_driver *drv)
+{
+       return !!acpi_match_device(drv->acpi_match_table, dev);
+}
+
+#define ACPI_PTR(_ptr) (_ptr)
+
 #else  /* !CONFIG_ACPI */
 
 #define acpi_disabled 1
@@ -418,6 +455,22 @@ static inline int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *),
        return 0;
 }
 
+struct acpi_device_id;
+
+static inline const struct acpi_device_id *acpi_match_device(
+       const struct acpi_device_id *ids, const struct device *dev)
+{
+       return NULL;
+}
+
+static inline bool acpi_driver_match_device(struct device *dev,
+                                           const struct device_driver *drv)
+{
+       return false;
+}
+
+#define ACPI_PTR(_ptr) (NULL)
+
 #endif /* !CONFIG_ACPI */
 
 #ifdef CONFIG_ACPI
@@ -430,4 +483,84 @@ acpi_status acpi_os_prepare_sleep(u8 sleep_state,
 #define acpi_os_set_prepare_sleep(func, pm1a_ctrl, pm1b_ctrl) do { } while (0)
 #endif
 
+#if defined(CONFIG_ACPI) && defined(CONFIG_PM_RUNTIME)
+int acpi_dev_runtime_suspend(struct device *dev);
+int acpi_dev_runtime_resume(struct device *dev);
+int acpi_subsys_runtime_suspend(struct device *dev);
+int acpi_subsys_runtime_resume(struct device *dev);
+#else
+static inline int acpi_dev_runtime_suspend(struct device *dev) { return 0; }
+static inline int acpi_dev_runtime_resume(struct device *dev) { return 0; }
+static inline int acpi_subsys_runtime_suspend(struct device *dev) { return 0; }
+static inline int acpi_subsys_runtime_resume(struct device *dev) { return 0; }
+#endif
+
+#ifdef CONFIG_ACPI_SLEEP
+int acpi_dev_suspend_late(struct device *dev);
+int acpi_dev_resume_early(struct device *dev);
+int acpi_subsys_prepare(struct device *dev);
+int acpi_subsys_suspend_late(struct device *dev);
+int acpi_subsys_resume_early(struct device *dev);
+#else
+static inline int acpi_dev_suspend_late(struct device *dev) { return 0; }
+static inline int acpi_dev_resume_early(struct device *dev) { return 0; }
+static inline int acpi_subsys_prepare(struct device *dev) { return 0; }
+static inline int acpi_subsys_suspend_late(struct device *dev) { return 0; }
+static inline int acpi_subsys_resume_early(struct device *dev) { return 0; }
+#endif
+
+#if defined(CONFIG_ACPI) && defined(CONFIG_PM)
+int acpi_dev_pm_attach(struct device *dev, bool power_on);
+void acpi_dev_pm_detach(struct device *dev, bool power_off);
+#else
+static inline int acpi_dev_pm_attach(struct device *dev, bool power_on)
+{
+       return -ENODEV;
+}
+static inline void acpi_dev_pm_detach(struct device *dev, bool power_off) {}
+#endif
+
+#ifdef CONFIG_ACPI
+__printf(3, 4)
+void acpi_handle_printk(const char *level, acpi_handle handle,
+                       const char *fmt, ...);
+#else  /* !CONFIG_ACPI */
+static inline __printf(3, 4) void
+acpi_handle_printk(const char *level, void *handle, const char *fmt, ...) {}
+#endif /* !CONFIG_ACPI */
+
+/*
+ * acpi_handle_<level>: Print message with ACPI prefix and object path
+ *
+ * These interfaces acquire the global namespace mutex to obtain an object
+ * path.  In interrupt context, it shows the object path as <n/a>.
+ */
+#define acpi_handle_emerg(handle, fmt, ...)                            \
+       acpi_handle_printk(KERN_EMERG, handle, fmt, ##__VA_ARGS__)
+#define acpi_handle_alert(handle, fmt, ...)                            \
+       acpi_handle_printk(KERN_ALERT, handle, fmt, ##__VA_ARGS__)
+#define acpi_handle_crit(handle, fmt, ...)                             \
+       acpi_handle_printk(KERN_CRIT, handle, fmt, ##__VA_ARGS__)
+#define acpi_handle_err(handle, fmt, ...)                              \
+       acpi_handle_printk(KERN_ERR, handle, fmt, ##__VA_ARGS__)
+#define acpi_handle_warn(handle, fmt, ...)                             \
+       acpi_handle_printk(KERN_WARNING, handle, fmt, ##__VA_ARGS__)
+#define acpi_handle_notice(handle, fmt, ...)                           \
+       acpi_handle_printk(KERN_NOTICE, handle, fmt, ##__VA_ARGS__)
+#define acpi_handle_info(handle, fmt, ...)                             \
+       acpi_handle_printk(KERN_INFO, handle, fmt, ##__VA_ARGS__)
+
+/* REVISIT: Support CONFIG_DYNAMIC_DEBUG when necessary */
+#if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
+#define acpi_handle_debug(handle, fmt, ...)                            \
+       acpi_handle_printk(KERN_DEBUG, handle, fmt, ##__VA_ARGS__)
+#else
+#define acpi_handle_debug(handle, fmt, ...)                            \
+({                                                                     \
+       if (0)                                                          \
+               acpi_handle_printk(KERN_DEBUG, handle, fmt, ##__VA_ARGS__); \
+       0;                                                              \
+})
+#endif
+
 #endif /*_LINUX_ACPI_H*/
diff --git a/include/linux/acpi_gpio.h b/include/linux/acpi_gpio.h
new file mode 100644 (file)
index 0000000..91615a3
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef _LINUX_ACPI_GPIO_H_
+#define _LINUX_ACPI_GPIO_H_
+
+#include <linux/errno.h>
+
+#ifdef CONFIG_GPIO_ACPI
+
+int acpi_get_gpio(char *path, int pin);
+
+#else /* CONFIG_GPIO_ACPI */
+
+static inline int acpi_get_gpio(char *path, int pin)
+{
+       return -ENODEV;
+}
+
+#endif /* CONFIG_GPIO_ACPI */
+
+#endif /* _LINUX_ACPI_GPIO_H_ */
index aaac4bb..b1cf40d 100644 (file)
@@ -15,6 +15,7 @@ struct pt_regs;
 #define BUILD_BUG_ON_NOT_POWER_OF_2(n)
 #define BUILD_BUG_ON_ZERO(e) (0)
 #define BUILD_BUG_ON_NULL(e) ((void*)0)
+#define BUILD_BUG_ON_INVALID(e) (0)
 #define BUILD_BUG_ON(condition)
 #define BUILD_BUG() (0)
 #else /* __CHECKER__ */
diff --git a/include/linux/byteorder/Kbuild b/include/linux/byteorder/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/include/linux/caif/Kbuild b/include/linux/caif/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/include/linux/can/Kbuild b/include/linux/can/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index c127315..4989b8a 100644 (file)
@@ -53,9 +53,18 @@ struct clk_hw;
  * @disable:   Disable the clock atomically. Called with enable_lock held.
  *             This function must not sleep.
  *
- * @recalc_rate        Recalculate the rate of this clock, by quering hardware.  The
+ * @is_enabled:        Queries the hardware to determine if the clock is enabled.
+ *             This function must not sleep. Optional, if this op is not
+ *             set then the enable count will be used.
+ *
+ * @disable_unused: Disable the clock atomically.  Only called from
+ *             clk_disable_unused for gate clocks with special needs.
+ *             Called with enable_lock held.  This function must not
+ *             sleep.
+ *
+ * @recalc_rate        Recalculate the rate of this clock, by querying hardware. The
  *             parent rate is an input parameter.  It is up to the caller to
- *             insure that the prepare_mutex is held across this call.
+ *             ensure that the prepare_mutex is held across this call.
  *             Returns the calculated rate.  Optional, but recommended - if
  *             this op is not set then clock rate will be initialized to 0.
  *
@@ -89,7 +98,7 @@ struct clk_hw;
  * implementations to split any work between atomic (enable) and sleepable
  * (prepare) contexts.  If enabling a clock requires code that might sleep,
  * this must be done in clk_prepare.  Clock enable code that will never be
- * called in a sleepable context may be implement in clk_enable.
+ * called in a sleepable context may be implemented in clk_enable.
  *
  * Typically, drivers will call clk_prepare when a clock may be needed later
  * (eg. when a device is opened), and clk_enable when the clock is actually
@@ -102,6 +111,7 @@ struct clk_ops {
        int             (*enable)(struct clk_hw *hw);
        void            (*disable)(struct clk_hw *hw);
        int             (*is_enabled)(struct clk_hw *hw);
+       void            (*disable_unused)(struct clk_hw *hw);
        unsigned long   (*recalc_rate)(struct clk_hw *hw,
                                        unsigned long parent_rate);
        long            (*round_rate)(struct clk_hw *hw, unsigned long,
@@ -327,19 +337,21 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
  * error code; drivers must test for an error code after calling clk_register.
  */
 struct clk *clk_register(struct device *dev, struct clk_hw *hw);
+struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw);
 
 void clk_unregister(struct clk *clk);
+void devm_clk_unregister(struct device *dev, struct clk *clk);
 
 /* helper functions */
 const char *__clk_get_name(struct clk *clk);
 struct clk_hw *__clk_get_hw(struct clk *clk);
 u8 __clk_get_num_parents(struct clk *clk);
 struct clk *__clk_get_parent(struct clk *clk);
-inline int __clk_get_enable_count(struct clk *clk);
-inline int __clk_get_prepare_count(struct clk *clk);
+unsigned int __clk_get_enable_count(struct clk *clk);
+unsigned int __clk_get_prepare_count(struct clk *clk);
 unsigned long __clk_get_rate(struct clk *clk);
 unsigned long __clk_get_flags(struct clk *clk);
-int __clk_is_enabled(struct clk *clk);
+bool __clk_is_enabled(struct clk *clk);
 struct clk *__clk_lookup(const char *name);
 
 /*
index 1775eb8..1d73993 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 b60f6ba..a55b88e 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)
 
 
 /*********************************************************************
@@ -404,6 +407,4 @@ void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
                                      unsigned int cpu);
 
 void cpufreq_frequency_table_put_attr(unsigned int cpu);
-
-
 #endif /* _LINUX_CPUFREQ_H */
index 279b1ea..3711b34 100644 (file)
@@ -82,13 +82,6 @@ cpuidle_set_statedata(struct cpuidle_state_usage *st_usage, void *data)
        st_usage->driver_data = data;
 }
 
-struct cpuidle_state_kobj {
-       struct cpuidle_state *state;
-       struct cpuidle_state_usage *state_usage;
-       struct completion kobj_unregister;
-       struct kobject kobj;
-};
-
 struct cpuidle_device {
        unsigned int            registered:1;
        unsigned int            enabled:1;
@@ -98,7 +91,7 @@ struct cpuidle_device {
        int                     state_count;
        struct cpuidle_state_usage      states_usage[CPUIDLE_STATE_MAX];
        struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
-
+       struct cpuidle_driver_kobj *kobj_driver;
        struct list_head        device_list;
        struct kobject          kobj;
        struct completion       kobj_unregister;
@@ -131,6 +124,7 @@ static inline int cpuidle_get_last_residency(struct cpuidle_device *dev)
 struct cpuidle_driver {
        const char              *name;
        struct module           *owner;
+       int                     refcnt;
 
        unsigned int            power_specified:1;
        /* set to 1 to use the core cpuidle time keeping (for all states). */
@@ -163,6 +157,10 @@ extern int cpuidle_wrap_enter(struct cpuidle_device *dev,
                                        struct cpuidle_driver *drv, int index));
 extern int cpuidle_play_dead(void);
 
+extern struct cpuidle_driver *cpuidle_get_cpu_driver(struct cpuidle_device *dev);
+extern int cpuidle_register_cpu_driver(struct cpuidle_driver *drv, int cpu);
+extern void cpuidle_unregister_cpu_driver(struct cpuidle_driver *drv, int cpu);
+
 #else
 static inline void disable_cpuidle(void) { }
 static inline int cpuidle_idle_call(void) { return -ENODEV; }
@@ -189,7 +187,6 @@ static inline int cpuidle_wrap_enter(struct cpuidle_device *dev,
                                        struct cpuidle_driver *drv, int index))
 { return -ENODEV; }
 static inline int cpuidle_play_dead(void) {return -ENODEV; }
-
 #endif
 
 #ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED
index 281c72a..e83ef39 100644 (file)
@@ -25,12 +25,12 @@ struct devfreq;
  * struct devfreq_dev_status - Data given from devfreq user device to
  *                          governors. Represents the performance
  *                          statistics.
- * @total_time         The total time represented by this instance of
+ * @total_time:                The total time represented by this instance of
  *                     devfreq_dev_status
- * @busy_time          The time that the device was working among the
+ * @busy_time:         The time that the device was working among the
  *                     total_time.
- * @current_frequency  The operating frequency.
- * @private_data       An entry not specified by the devfreq framework.
+ * @current_frequency: The operating frequency.
+ * @private_data:      An entry not specified by the devfreq framework.
  *                     A device and a specific governor may have their
  *                     own protocol with private_data. However, because
  *                     this is governor-specific, a governor using this
@@ -54,23 +54,27 @@ struct devfreq_dev_status {
 
 /**
  * struct devfreq_dev_profile - Devfreq's user device profile
- * @initial_freq       The operating frequency when devfreq_add_device() is
+ * @initial_freq:      The operating frequency when devfreq_add_device() is
  *                     called.
- * @polling_ms         The polling interval in ms. 0 disables polling.
- * @target             The device should set its operating frequency at
+ * @polling_ms:                The polling interval in ms. 0 disables polling.
+ * @target:            The device should set its operating frequency at
  *                     freq or lowest-upper-than-freq value. If freq is
  *                     higher than any operable frequency, set maximum.
  *                     Before returning, target function should set
  *                     freq at the current frequency.
  *                     The "flags" parameter's possible values are
  *                     explained above with "DEVFREQ_FLAG_*" macros.
- * @get_dev_status     The device should provide the current performance
+ * @get_dev_status:    The device should provide the current performance
  *                     status to devfreq, which is used by governors.
- * @exit               An optional callback that is called when devfreq
+ * @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
  *                     has registered devfreq->nb at a notifier-head,
  *                     this is the time to unregister it.
+ * @freq_table:        Optional list of frequencies to support statistics.
+ * @max_state: The size of freq_table.
  */
 struct devfreq_dev_profile {
        unsigned long initial_freq;
@@ -79,63 +83,63 @@ 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);
+
+       unsigned int *freq_table;
+       unsigned int max_state;
 };
 
 /**
  * struct devfreq_governor - Devfreq policy governor
- * @name               Governor's name
- * @get_target_freq    Returns desired operating frequency for the device.
+ * @node:              list node - contains registered devfreq governors
+ * @name:              Governor's name
+ * @get_target_freq:   Returns desired operating frequency for the device.
  *                     Basically, get_target_freq will run
  *                     devfreq_dev_profile.get_dev_status() to get the
  *                     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 {
+       struct list_head node;
+
        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);
 };
 
 /**
  * struct devfreq - Device devfreq structure
- * @node       list node - contains the devices with devfreq that have been
+ * @node:      list node - contains the devices with devfreq that have been
  *             registered.
- * @lock       a mutex to protect accessing devfreq.
- * @dev                device registered by devfreq class. dev.parent is the device
+ * @lock:      a mutex to protect accessing devfreq.
+ * @dev:       device registered by devfreq class. dev.parent is the device
  *             using devfreq.
- * @profile    device-specific devfreq profile
- * @governor   method how to choose frequency based on the usage.
- * @nb         notifier block used to notify devfreq object that it should
+ * @profile:   device-specific devfreq profile
+ * @governor:  method how to choose frequency based on the usage.
+ * @governor_name:     devfreq governor name for use with this devfreq
+ * @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.
- * @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
+ * @work:      delayed work for load monitoring.
+ * @previous_freq:     previously configured frequency value.
+ * @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)
+ * @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.
+ * @total_trans:       Number of devfreq transitions
+ * @trans_table:       Statistics of devfreq transitions
+ * @time_in_state:     Statistics of devfreq states
+ * @last_stat_updated: The last time stat updated
  *
  * This structure stores the devfreq information for a give device.
  *
@@ -152,26 +156,33 @@ struct devfreq {
        struct device dev;
        struct devfreq_dev_profile *profile;
        const struct devfreq_governor *governor;
+       char governor_name[DEVFREQ_NAME_LEN];
        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;
+
+       /* information for device freqeuncy transition */
+       unsigned int total_trans;
+       unsigned int *trans_table;
+       unsigned long *time_in_state;
+       unsigned long last_stat_updated;
 };
 
 #if defined(CONFIG_PM_DEVFREQ)
 extern struct devfreq *devfreq_add_device(struct device *dev,
                                  struct devfreq_dev_profile *profile,
-                                 const struct devfreq_governor *governor,
+                                 const char *governor_name,
                                  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,
@@ -181,23 +192,13 @@ extern int devfreq_register_opp_notifier(struct device *dev,
 extern int devfreq_unregister_opp_notifier(struct device *dev,
                                           struct devfreq *devfreq);
 
-#ifdef CONFIG_DEVFREQ_GOV_POWERSAVE
-extern const struct devfreq_governor devfreq_powersave;
-#endif
-#ifdef CONFIG_DEVFREQ_GOV_PERFORMANCE
-extern const struct devfreq_governor devfreq_performance;
-#endif
-#ifdef CONFIG_DEVFREQ_GOV_USERSPACE
-extern const struct devfreq_governor devfreq_userspace;
-#endif
-#ifdef CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND
-extern const struct devfreq_governor devfreq_simple_ondemand;
+#if IS_ENABLED(CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND)
 /**
  * struct devfreq_simple_ondemand_data - void *data fed to struct devfreq
  *     and devfreq_add_device
- * @ upthreshold       If the load is over this value, the frequency jumps.
+ * @upthreshold:       If the load is over this value, the frequency jumps.
  *                     Specify 0 to use the default. Valid value = 0 to 100.
- * @ downdifferential  If the load is under upthreshold - downdifferential,
+ * @downdifferential:  If the load is under upthreshold - downdifferential,
  *                     the governor may consider slowing the frequency down.
  *                     Specify 0 to use the default. Valid value = 0 to 100.
  *                     downdifferential < upthreshold must hold.
@@ -214,7 +215,7 @@ struct devfreq_simple_ondemand_data {
 #else /* !CONFIG_PM_DEVFREQ */
 static struct devfreq *devfreq_add_device(struct device *dev,
                                          struct devfreq_dev_profile *profile,
-                                         struct devfreq_governor *governor,
+                                         const char *governor_name,
                                          void *data)
 {
        return NULL;
@@ -225,6 +226,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)
 {
@@ -243,11 +254,6 @@ static int devfreq_unregister_opp_notifier(struct device *dev,
        return -EINVAL;
 }
 
-#define devfreq_powersave      NULL
-#define devfreq_performance    NULL
-#define devfreq_userspace      NULL
-#define devfreq_simple_ondemand        NULL
-
 #endif /* CONFIG_PM_DEVFREQ */
 
 #endif /* __LINUX_DEVFREQ_H__ */
index 86ef6ab..05292e4 100644 (file)
@@ -190,6 +190,7 @@ extern struct klist *bus_get_device_klist(struct bus_type *bus);
  * @mod_name:  Used for built-in modules.
  * @suppress_bind_attrs: Disables bind/unbind via sysfs.
  * @of_match_table: The open firmware table.
+ * @acpi_match_table: The ACPI match table.
  * @probe:     Called to query the existence of a specific device,
  *             whether this driver can work with it, and bind the driver
  *             to a specific device.
@@ -223,6 +224,7 @@ struct device_driver {
        bool suppress_bind_attrs;       /* disables bind/unbind via sysfs */
 
        const struct of_device_id       *of_match_table;
+       const struct acpi_device_id     *acpi_match_table;
 
        int (*probe) (struct device *dev);
        int (*remove) (struct device *dev);
@@ -576,6 +578,12 @@ struct device_dma_parameters {
        unsigned long segment_boundary_mask;
 };
 
+struct acpi_dev_node {
+#ifdef CONFIG_ACPI
+       void    *handle;
+#endif
+};
+
 /**
  * struct device - The basic device structure
  * @parent:    The device's "parent" device, the device to which it is attached.
@@ -616,6 +624,7 @@ struct device_dma_parameters {
  * @dma_mem:   Internal for coherent mem override.
  * @archdata:  For arch-specific additions.
  * @of_node:   Associated device tree node.
+ * @acpi_node: Associated ACPI device node.
  * @devt:      For creating the sysfs "dev".
  * @id:                device instance
  * @devres_lock: Spinlock to protect the resource of the device.
@@ -680,6 +689,7 @@ struct device {
        struct dev_archdata     archdata;
 
        struct device_node      *of_node; /* associated device tree node */
+       struct acpi_dev_node    acpi_node; /* associated ACPI device node */
 
        dev_t                   devt;   /* dev_t, creates the sysfs "dev" */
        u32                     id;     /* device instance */
@@ -700,6 +710,14 @@ static inline struct device *kobj_to_dev(struct kobject *kobj)
        return container_of(kobj, struct device, kobj);
 }
 
+#ifdef CONFIG_ACPI
+#define ACPI_HANDLE(dev)       ((dev)->acpi_node.handle)
+#define ACPI_HANDLE_SET(dev, _handle_) (dev)->acpi_node.handle = (_handle_)
+#else
+#define ACPI_HANDLE(dev)       (NULL)
+#define ACPI_HANDLE_SET(dev, _handle_) do { } while (0)
+#endif
+
 /* Get the wakeup routines, which depend on struct device */
 #include <linux/pm_wakeup.h>
 
index 2f303e4..01b5c84 100644 (file)
@@ -68,7 +68,7 @@ struct device;
 extern struct cma *dma_contiguous_default_area;
 
 void dma_contiguous_reserve(phys_addr_t addr_limit);
-int dma_declare_contiguous(struct device *dev, unsigned long size,
+int dma_declare_contiguous(struct device *dev, phys_addr_t size,
                           phys_addr_t base, phys_addr_t limit);
 
 struct page *dma_alloc_from_contiguous(struct device *dev, int count,
@@ -83,7 +83,7 @@ bool dma_release_from_contiguous(struct device *dev, struct page *pages,
 static inline void dma_contiguous_reserve(phys_addr_t limit) { }
 
 static inline
-int dma_declare_contiguous(struct device *dev, unsigned long size,
+int dma_declare_contiguous(struct device *dev, phys_addr_t size,
                           phys_addr_t base, phys_addr_t limit)
 {
        return -ENOSYS;
index f4dba86..e69de29 100644 (file)
@@ -1,8 +0,0 @@
-header-y += audio.h
-header-y += ca.h
-header-y += dmx.h
-header-y += frontend.h
-header-y += net.h
-header-y += osd.h
-header-y += version.h
-header-y += video.h
index f078f3a..0be6d8f 100644 (file)
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  *
  */
-
 #ifndef _DVBDMX_H_
 #define _DVBDMX_H_
 
-#include <linux/types.h>
-#ifdef __KERNEL__
 #include <linux/time.h>
-#else
-#include <time.h>
-#endif
-
-
-#define DMX_FILTER_SIZE 16
-
-typedef enum
-{
-       DMX_OUT_DECODER, /* Streaming directly to decoder. */
-       DMX_OUT_TAP,     /* Output going to a memory buffer */
-                        /* (to be retrieved via the read command).*/
-       DMX_OUT_TS_TAP,  /* Output multiplexed into a new TS  */
-                        /* (to be retrieved by reading from the */
-                        /* logical DVR device).                 */
-       DMX_OUT_TSDEMUX_TAP /* Like TS_TAP but retrieved from the DMX device */
-} dmx_output_t;
-
-
-typedef enum
-{
-       DMX_IN_FRONTEND, /* Input from a front-end device.  */
-       DMX_IN_DVR       /* Input from the logical DVR device.  */
-} dmx_input_t;
-
-
-typedef enum
-{
-       DMX_PES_AUDIO0,
-       DMX_PES_VIDEO0,
-       DMX_PES_TELETEXT0,
-       DMX_PES_SUBTITLE0,
-       DMX_PES_PCR0,
-
-       DMX_PES_AUDIO1,
-       DMX_PES_VIDEO1,
-       DMX_PES_TELETEXT1,
-       DMX_PES_SUBTITLE1,
-       DMX_PES_PCR1,
-
-       DMX_PES_AUDIO2,
-       DMX_PES_VIDEO2,
-       DMX_PES_TELETEXT2,
-       DMX_PES_SUBTITLE2,
-       DMX_PES_PCR2,
-
-       DMX_PES_AUDIO3,
-       DMX_PES_VIDEO3,
-       DMX_PES_TELETEXT3,
-       DMX_PES_SUBTITLE3,
-       DMX_PES_PCR3,
-
-       DMX_PES_OTHER
-} dmx_pes_type_t;
-
-#define DMX_PES_AUDIO    DMX_PES_AUDIO0
-#define DMX_PES_VIDEO    DMX_PES_VIDEO0
-#define DMX_PES_TELETEXT DMX_PES_TELETEXT0
-#define DMX_PES_SUBTITLE DMX_PES_SUBTITLE0
-#define DMX_PES_PCR      DMX_PES_PCR0
-
-
-typedef struct dmx_filter
-{
-       __u8  filter[DMX_FILTER_SIZE];
-       __u8  mask[DMX_FILTER_SIZE];
-       __u8  mode[DMX_FILTER_SIZE];
-} dmx_filter_t;
-
-
-struct dmx_sct_filter_params
-{
-       __u16          pid;
-       dmx_filter_t   filter;
-       __u32          timeout;
-       __u32          flags;
-#define DMX_CHECK_CRC       1
-#define DMX_ONESHOT         2
-#define DMX_IMMEDIATE_START 4
-#define DMX_KERNEL_CLIENT   0x8000
-};
-
-
-struct dmx_pes_filter_params
-{
-       __u16          pid;
-       dmx_input_t    input;
-       dmx_output_t   output;
-       dmx_pes_type_t pes_type;
-       __u32          flags;
-};
-
-typedef struct dmx_caps {
-       __u32 caps;
-       int num_decoders;
-} dmx_caps_t;
-
-typedef enum {
-       DMX_SOURCE_FRONT0 = 0,
-       DMX_SOURCE_FRONT1,
-       DMX_SOURCE_FRONT2,
-       DMX_SOURCE_FRONT3,
-       DMX_SOURCE_DVR0   = 16,
-       DMX_SOURCE_DVR1,
-       DMX_SOURCE_DVR2,
-       DMX_SOURCE_DVR3
-} dmx_source_t;
-
-struct dmx_stc {
-       unsigned int num;       /* input : which STC? 0..N */
-       unsigned int base;      /* output: divisor for stc to get 90 kHz clock */
-       __u64 stc;              /* output: stc in 'base'*90 kHz units */
-};
-
-
-#define DMX_START                _IO('o', 41)
-#define DMX_STOP                 _IO('o', 42)
-#define DMX_SET_FILTER           _IOW('o', 43, struct dmx_sct_filter_params)
-#define DMX_SET_PES_FILTER       _IOW('o', 44, struct dmx_pes_filter_params)
-#define DMX_SET_BUFFER_SIZE      _IO('o', 45)
-#define DMX_GET_PES_PIDS         _IOR('o', 47, __u16[5])
-#define DMX_GET_CAPS             _IOR('o', 48, dmx_caps_t)
-#define DMX_SET_SOURCE           _IOW('o', 49, dmx_source_t)
-#define DMX_GET_STC              _IOWR('o', 50, struct dmx_stc)
-#define DMX_ADD_PID              _IOW('o', 51, __u16)
-#define DMX_REMOVE_PID           _IOW('o', 52, __u16)
+#include <uapi/linux/dvb/dmx.h>
 
 #endif /*_DVBDMX_H_*/
index 1d750c0..85c20d9 100644 (file)
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  *
  */
-
 #ifndef _DVBVIDEO_H_
 #define _DVBVIDEO_H_
 
-#include <linux/types.h>
-#ifdef __KERNEL__
 #include <linux/compiler.h>
-#else
-#include <stdint.h>
-#include <time.h>
-#endif
-
-typedef enum {
-       VIDEO_FORMAT_4_3,     /* Select 4:3 format */
-       VIDEO_FORMAT_16_9,    /* Select 16:9 format. */
-       VIDEO_FORMAT_221_1    /* 2.21:1 */
-} video_format_t;
-
-
-typedef enum {
-        VIDEO_SYSTEM_PAL,
-        VIDEO_SYSTEM_NTSC,
-        VIDEO_SYSTEM_PALN,
-        VIDEO_SYSTEM_PALNc,
-        VIDEO_SYSTEM_PALM,
-        VIDEO_SYSTEM_NTSC60,
-        VIDEO_SYSTEM_PAL60,
-        VIDEO_SYSTEM_PALM60
-} video_system_t;
-
-
-typedef enum {
-       VIDEO_PAN_SCAN,       /* use pan and scan format */
-       VIDEO_LETTER_BOX,     /* use letterbox format */
-       VIDEO_CENTER_CUT_OUT  /* use center cut out format */
-} video_displayformat_t;
-
-typedef struct {
-       int w;
-       int h;
-       video_format_t aspect_ratio;
-} video_size_t;
-
-typedef enum {
-       VIDEO_SOURCE_DEMUX, /* Select the demux as the main source */
-       VIDEO_SOURCE_MEMORY /* If this source is selected, the stream
-                              comes from the user through the write
-                              system call */
-} video_stream_source_t;
-
-
-typedef enum {
-       VIDEO_STOPPED, /* Video is stopped */
-       VIDEO_PLAYING, /* Video is currently playing */
-       VIDEO_FREEZED  /* Video is freezed */
-} video_play_state_t;
-
-
-/* Decoder commands */
-#define VIDEO_CMD_PLAY        (0)
-#define VIDEO_CMD_STOP        (1)
-#define VIDEO_CMD_FREEZE      (2)
-#define VIDEO_CMD_CONTINUE    (3)
-
-/* Flags for VIDEO_CMD_FREEZE */
-#define VIDEO_CMD_FREEZE_TO_BLACK      (1 << 0)
-
-/* Flags for VIDEO_CMD_STOP */
-#define VIDEO_CMD_STOP_TO_BLACK        (1 << 0)
-#define VIDEO_CMD_STOP_IMMEDIATELY             (1 << 1)
-
-/* Play input formats: */
-/* The decoder has no special format requirements */
-#define VIDEO_PLAY_FMT_NONE         (0)
-/* The decoder requires full GOPs */
-#define VIDEO_PLAY_FMT_GOP          (1)
-
-/* The structure must be zeroed before use by the application
-   This ensures it can be extended safely in the future. */
-struct video_command {
-       __u32 cmd;
-       __u32 flags;
-       union {
-               struct {
-                       __u64 pts;
-               } stop;
-
-               struct {
-                       /* 0 or 1000 specifies normal speed,
-                          1 specifies forward single stepping,
-                          -1 specifies backward single stepping,
-                          >1: playback at speed/1000 of the normal speed,
-                          <-1: reverse playback at (-speed/1000) of the normal speed. */
-                       __s32 speed;
-                       __u32 format;
-               } play;
-
-               struct {
-                       __u32 data[16];
-               } raw;
-       };
-};
-
-/* FIELD_UNKNOWN can be used if the hardware does not know whether
-   the Vsync is for an odd, even or progressive (i.e. non-interlaced)
-   field. */
-#define VIDEO_VSYNC_FIELD_UNKNOWN      (0)
-#define VIDEO_VSYNC_FIELD_ODD          (1)
-#define VIDEO_VSYNC_FIELD_EVEN         (2)
-#define VIDEO_VSYNC_FIELD_PROGRESSIVE  (3)
-
-struct video_event {
-       __s32 type;
-#define VIDEO_EVENT_SIZE_CHANGED       1
-#define VIDEO_EVENT_FRAME_RATE_CHANGED 2
-#define VIDEO_EVENT_DECODER_STOPPED    3
-#define VIDEO_EVENT_VSYNC              4
-       __kernel_time_t timestamp;
-       union {
-               video_size_t size;
-               unsigned int frame_rate;        /* in frames per 1000sec */
-               unsigned char vsync_field;      /* unknown/odd/even/progressive */
-       } u;
-};
-
-
-struct video_status {
-       int                   video_blank;   /* blank video on freeze? */
-       video_play_state_t    play_state;    /* current state of playback */
-       video_stream_source_t stream_source; /* current source (demux/memory) */
-       video_format_t        video_format;  /* current aspect ratio of stream*/
-       video_displayformat_t display_format;/* selected cropping mode */
-};
-
-
-struct video_still_picture {
-       char __user *iFrame;        /* pointer to a single iframe in memory */
-       __s32 size;
-};
-
-
-typedef
-struct video_highlight {
-       int     active;      /*    1=show highlight, 0=hide highlight */
-       __u8    contrast1;   /*    7- 4  Pattern pixel contrast */
-                            /*    3- 0  Background pixel contrast */
-       __u8    contrast2;   /*    7- 4  Emphasis pixel-2 contrast */
-                            /*    3- 0  Emphasis pixel-1 contrast */
-       __u8    color1;      /*    7- 4  Pattern pixel color */
-                            /*    3- 0  Background pixel color */
-       __u8    color2;      /*    7- 4  Emphasis pixel-2 color */
-                            /*    3- 0  Emphasis pixel-1 color */
-       __u32    ypos;       /*   23-22  auto action mode */
-                            /*   21-12  start y */
-                            /*    9- 0  end y */
-       __u32    xpos;       /*   23-22  button color number */
-                            /*   21-12  start x */
-                            /*    9- 0  end x */
-} video_highlight_t;
-
-
-typedef struct video_spu {
-       int active;
-       int stream_id;
-} video_spu_t;
-
-
-typedef struct video_spu_palette {      /* SPU Palette information */
-       int length;
-       __u8 __user *palette;
-} video_spu_palette_t;
-
-
-typedef struct video_navi_pack {
-       int length;          /* 0 ... 1024 */
-       __u8 data[1024];
-} video_navi_pack_t;
-
-
-typedef __u16 video_attributes_t;
-/*   bits: descr. */
-/*   15-14 Video compression mode (0=MPEG-1, 1=MPEG-2) */
-/*   13-12 TV system (0=525/60, 1=625/50) */
-/*   11-10 Aspect ratio (0=4:3, 3=16:9) */
-/*    9- 8 permitted display mode on 4:3 monitor (0=both, 1=only pan-sca */
-/*    7    line 21-1 data present in GOP (1=yes, 0=no) */
-/*    6    line 21-2 data present in GOP (1=yes, 0=no) */
-/*    5- 3 source resolution (0=720x480/576, 1=704x480/576, 2=352x480/57 */
-/*    2    source letterboxed (1=yes, 0=no) */
-/*    0    film/camera mode (0=camera, 1=film (625/50 only)) */
-
-
-/* bit definitions for capabilities: */
-/* can the hardware decode MPEG1 and/or MPEG2? */
-#define VIDEO_CAP_MPEG1   1
-#define VIDEO_CAP_MPEG2   2
-/* can you send a system and/or program stream to video device?
-   (you still have to open the video and the audio device but only
-    send the stream to the video device) */
-#define VIDEO_CAP_SYS     4
-#define VIDEO_CAP_PROG    8
-/* can the driver also handle SPU, NAVI and CSS encoded data?
-   (CSS API is not present yet) */
-#define VIDEO_CAP_SPU    16
-#define VIDEO_CAP_NAVI   32
-#define VIDEO_CAP_CSS    64
-
-
-#define VIDEO_STOP                 _IO('o', 21)
-#define VIDEO_PLAY                 _IO('o', 22)
-#define VIDEO_FREEZE               _IO('o', 23)
-#define VIDEO_CONTINUE             _IO('o', 24)
-#define VIDEO_SELECT_SOURCE        _IO('o', 25)
-#define VIDEO_SET_BLANK            _IO('o', 26)
-#define VIDEO_GET_STATUS           _IOR('o', 27, struct video_status)
-#define VIDEO_GET_EVENT            _IOR('o', 28, struct video_event)
-#define VIDEO_SET_DISPLAY_FORMAT   _IO('o', 29)
-#define VIDEO_STILLPICTURE         _IOW('o', 30, struct video_still_picture)
-#define VIDEO_FAST_FORWARD         _IO('o', 31)
-#define VIDEO_SLOWMOTION           _IO('o', 32)
-#define VIDEO_GET_CAPABILITIES     _IOR('o', 33, unsigned int)
-#define VIDEO_CLEAR_BUFFER         _IO('o',  34)
-#define VIDEO_SET_ID               _IO('o', 35)
-#define VIDEO_SET_STREAMTYPE       _IO('o', 36)
-#define VIDEO_SET_FORMAT           _IO('o', 37)
-#define VIDEO_SET_SYSTEM           _IO('o', 38)
-#define VIDEO_SET_HIGHLIGHT        _IOW('o', 39, video_highlight_t)
-#define VIDEO_SET_SPU              _IOW('o', 50, video_spu_t)
-#define VIDEO_SET_SPU_PALETTE      _IOW('o', 51, video_spu_palette_t)
-#define VIDEO_GET_NAVI             _IOR('o', 52, video_navi_pack_t)
-#define VIDEO_SET_ATTRIBUTES       _IO('o', 53)
-#define VIDEO_GET_SIZE             _IOR('o', 55, video_size_t)
-#define VIDEO_GET_FRAME_RATE       _IOR('o', 56, unsigned int)
-
-/**
- * VIDEO_GET_PTS
- *
- * Read the 33 bit presentation time stamp as defined
- * in ITU T-REC-H.222.0 / ISO/IEC 13818-1.
- *
- * The PTS should belong to the currently played
- * frame if possible, but may also be a value close to it
- * like the PTS of the last decoded frame or the last PTS
- * extracted by the PES parser.
- */
-#define VIDEO_GET_PTS              _IOR('o', 57, __u64)
-
-/* Read the number of displayed frames since the decoder was started */
-#define VIDEO_GET_FRAME_COUNT             _IOR('o', 58, __u64)
-
-#define VIDEO_COMMAND             _IOWR('o', 59, struct video_command)
-#define VIDEO_TRY_COMMAND         _IOWR('o', 60, struct video_command)
+#include <uapi/linux/dvb/video.h>
 
 #endif /*_DVBVIDEO_H_*/
index c18257b..6dd4787 100644 (file)
@@ -61,7 +61,7 @@ int __dynamic_netdev_dbg(struct _ddebug *descriptor,
                         const char *fmt, ...);
 
 #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)               \
-       static struct _ddebug __used __aligned(8)               \
+       static struct _ddebug  __aligned(8)                     \
        __attribute__((section("__verbose"))) name = {          \
                .modname = KBUILD_MODNAME,                      \
                .function = __func__,                           \
index bab9f84..1b8c02b 100644 (file)
@@ -533,6 +533,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 +668,8 @@ struct mem_ctl_info {
        u32 fake_inject_ue;
        u16 fake_inject_count;
 #endif
+       __u8 csbased : 1,       /* csrow-based memory controller */
+            __resv  : 7;
 };
 
 #endif
diff --git a/include/linux/elf-fdpic.h b/include/linux/elf-fdpic.h
new file mode 100644 (file)
index 0000000..3864403
--- /dev/null
@@ -0,0 +1,51 @@
+/* FDPIC ELF load map
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.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.
+ */
+
+#ifndef _LINUX_ELF_FDPIC_H
+#define _LINUX_ELF_FDPIC_H
+
+#include <uapi/linux/elf-fdpic.h>
+
+/*
+ * binfmt binary parameters structure
+ */
+struct elf_fdpic_params {
+       struct elfhdr                   hdr;            /* ref copy of ELF header */
+       struct elf_phdr                 *phdrs;         /* ref copy of PT_PHDR table */
+       struct elf32_fdpic_loadmap      *loadmap;       /* loadmap to be passed to userspace */
+       unsigned long                   elfhdr_addr;    /* mapped ELF header user address */
+       unsigned long                   ph_addr;        /* mapped PT_PHDR user address */
+       unsigned long                   map_addr;       /* mapped loadmap user address */
+       unsigned long                   entry_addr;     /* mapped entry user address */
+       unsigned long                   stack_size;     /* stack size requested (PT_GNU_STACK) */
+       unsigned long                   dynamic_addr;   /* mapped PT_DYNAMIC user address */
+       unsigned long                   load_addr;      /* user address at which to map binary */
+       unsigned long                   flags;
+#define ELF_FDPIC_FLAG_ARRANGEMENT     0x0000000f      /* PT_LOAD arrangement flags */
+#define ELF_FDPIC_FLAG_INDEPENDENT     0x00000000      /* PT_LOADs can be put anywhere */
+#define ELF_FDPIC_FLAG_HONOURVADDR     0x00000001      /* PT_LOAD.vaddr must be honoured */
+#define ELF_FDPIC_FLAG_CONSTDISP       0x00000002      /* PT_LOADs require constant
+                                                        * displacement */
+#define ELF_FDPIC_FLAG_CONTIGUOUS      0x00000003      /* PT_LOADs should be contiguous */
+#define ELF_FDPIC_FLAG_EXEC_STACK      0x00000010      /* T if stack to be executable */
+#define ELF_FDPIC_FLAG_NOEXEC_STACK    0x00000020      /* T if stack not to be executable */
+#define ELF_FDPIC_FLAG_EXECUTABLE      0x00000040      /* T if this object is the executable */
+#define ELF_FDPIC_FLAG_PRESENT         0x80000000      /* T if this object is present */
+};
+
+#ifdef CONFIG_MMU
+extern void elf_fdpic_arch_lay_out_mm(struct elf_fdpic_params *exec_params,
+                                     struct elf_fdpic_params *interp_params,
+                                     unsigned long *start_stack,
+                                     unsigned long *start_brk);
+#endif
+
+#endif /* _LINUX_ELF_FDPIC_H */
index 7443a56..2c26c14 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 d09af4b..b90091a 100644 (file)
@@ -177,6 +177,7 @@ static inline int freeze_kernel_threads(void) { return -ENOSYS; }
 static inline void thaw_processes(void) {}
 static inline void thaw_kernel_threads(void) {}
 
+static inline bool try_to_freeze_nowarn(void) { return false; }
 static inline bool try_to_freeze(void) { return false; }
 
 static inline void freezer_do_not_count(void) {}
index 001c7cf..75fe9a1 100644 (file)
@@ -64,6 +64,73 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
                        ssize_t bytes, void *private, int ret,
                        bool is_async);
 
+#define MAY_EXEC               0x00000001
+#define MAY_WRITE              0x00000002
+#define MAY_READ               0x00000004
+#define MAY_APPEND             0x00000008
+#define MAY_ACCESS             0x00000010
+#define MAY_OPEN               0x00000020
+#define MAY_CHDIR              0x00000040
+/* called from RCU mode, don't block */
+#define MAY_NOT_BLOCK          0x00000080
+
+/*
+ * flags in file.f_mode.  Note that FMODE_READ and FMODE_WRITE must correspond
+ * to O_WRONLY and O_RDWR via the strange trick in __dentry_open()
+ */
+
+/* file is open for reading */
+#define FMODE_READ             ((__force fmode_t)0x1)
+/* file is open for writing */
+#define FMODE_WRITE            ((__force fmode_t)0x2)
+/* file is seekable */
+#define FMODE_LSEEK            ((__force fmode_t)0x4)
+/* file can be accessed using pread */
+#define FMODE_PREAD            ((__force fmode_t)0x8)
+/* file can be accessed using pwrite */
+#define FMODE_PWRITE           ((__force fmode_t)0x10)
+/* File is opened for execution with sys_execve / sys_uselib */
+#define FMODE_EXEC             ((__force fmode_t)0x20)
+/* File is opened with O_NDELAY (only set for block devices) */
+#define FMODE_NDELAY           ((__force fmode_t)0x40)
+/* File is opened with O_EXCL (only set for block devices) */
+#define FMODE_EXCL             ((__force fmode_t)0x80)
+/* File is opened using open(.., 3, ..) and is writeable only for ioctls
+   (specialy hack for floppy.c) */
+#define FMODE_WRITE_IOCTL      ((__force fmode_t)0x100)
+/* 32bit hashes as llseek() offset (for directories) */
+#define FMODE_32BITHASH         ((__force fmode_t)0x200)
+/* 64bit hashes as llseek() offset (for directories) */
+#define FMODE_64BITHASH         ((__force fmode_t)0x400)
+
+/*
+ * Don't update ctime and mtime.
+ *
+ * Currently a special hack for the XFS open_by_handle ioctl, but we'll
+ * hopefully graduate it to a proper O_CMTIME flag supported by open(2) soon.
+ */
+#define FMODE_NOCMTIME         ((__force fmode_t)0x800)
+
+/* Expect random access pattern */
+#define FMODE_RANDOM           ((__force fmode_t)0x1000)
+
+/* File is huge (eg. /dev/kmem): treat loff_t as unsigned */
+#define FMODE_UNSIGNED_OFFSET  ((__force fmode_t)0x2000)
+
+/* File is opened with O_PATH; almost nothing can be done with it */
+#define FMODE_PATH             ((__force fmode_t)0x4000)
+
+/* File was opened by fanotify and shouldn't generate fanotify events */
+#define FMODE_NONOTIFY         ((__force fmode_t)0x1000000)
+
+/*
+ * Flag for rw_copy_check_uvector and compat_rw_copy_check_uvector
+ * that indicates that they should check the contents of the iovec are
+ * valid, but not check the memory that the iovec elements
+ * points too.
+ */
+#define CHECK_IOVEC_ONLY -1
+
 /*
  * The below are the various read and write types that we support. Some of
  * them include behavioral modifiers that send information down to the
@@ -395,8 +462,6 @@ struct block_device {
        int                     bd_fsfreeze_count;
        /* Mutex for freeze */
        struct mutex            bd_fsfreeze_mutex;
-       /* A semaphore that prevents I/O while block size is being changed */
-       struct percpu_rw_semaphore      bd_block_size_semaphore;
 };
 
 /*
@@ -1557,6 +1622,60 @@ struct super_operations {
 };
 
 /*
+ * Inode flags - they have no relation to superblock flags now
+ */
+#define S_SYNC         1       /* Writes are synced at once */
+#define S_NOATIME      2       /* Do not update access times */
+#define S_APPEND       4       /* Append-only file */
+#define S_IMMUTABLE    8       /* Immutable file */
+#define S_DEAD         16      /* removed, but still open directory */
+#define S_NOQUOTA      32      /* Inode is not counted to quota */
+#define S_DIRSYNC      64      /* Directory modifications are synchronous */
+#define S_NOCMTIME     128     /* Do not update file c/mtime */
+#define S_SWAPFILE     256     /* Do not truncate: swapon got its bmaps */
+#define S_PRIVATE      512     /* Inode is fs-internal */
+#define S_IMA          1024    /* Inode has an associated IMA struct */
+#define S_AUTOMOUNT    2048    /* Automount/referral quasi-directory */
+#define S_NOSEC                4096    /* no suid or xattr security attributes */
+
+/*
+ * Note that nosuid etc flags are inode-specific: setting some file-system
+ * flags just means all the inodes inherit those flags by default. It might be
+ * possible to override it selectively if you really wanted to with some
+ * ioctl() that is not currently implemented.
+ *
+ * Exception: MS_RDONLY is always applied to the entire file system.
+ *
+ * Unfortunately, it is possible to change a filesystems flags with it mounted
+ * with files in use.  This means that all of the inodes will not have their
+ * i_flags updated.  Hence, i_flags no longer inherit the superblock mount
+ * flags, so these have to be checked separately. -- rmk@arm.uk.linux.org
+ */
+#define __IS_FLG(inode, flg)   ((inode)->i_sb->s_flags & (flg))
+
+#define IS_RDONLY(inode)       ((inode)->i_sb->s_flags & MS_RDONLY)
+#define IS_SYNC(inode)         (__IS_FLG(inode, MS_SYNCHRONOUS) || \
+                                       ((inode)->i_flags & S_SYNC))
+#define IS_DIRSYNC(inode)      (__IS_FLG(inode, MS_SYNCHRONOUS|MS_DIRSYNC) || \
+                                       ((inode)->i_flags & (S_SYNC|S_DIRSYNC)))
+#define IS_MANDLOCK(inode)     __IS_FLG(inode, MS_MANDLOCK)
+#define IS_NOATIME(inode)      __IS_FLG(inode, MS_RDONLY|MS_NOATIME)
+#define IS_I_VERSION(inode)    __IS_FLG(inode, MS_I_VERSION)
+
+#define IS_NOQUOTA(inode)      ((inode)->i_flags & S_NOQUOTA)
+#define IS_APPEND(inode)       ((inode)->i_flags & S_APPEND)
+#define IS_IMMUTABLE(inode)    ((inode)->i_flags & S_IMMUTABLE)
+#define IS_POSIXACL(inode)     __IS_FLG(inode, MS_POSIXACL)
+
+#define IS_DEADDIR(inode)      ((inode)->i_flags & S_DEAD)
+#define IS_NOCMTIME(inode)     ((inode)->i_flags & S_NOCMTIME)
+#define IS_SWAPFILE(inode)     ((inode)->i_flags & S_SWAPFILE)
+#define IS_PRIVATE(inode)      ((inode)->i_flags & S_PRIVATE)
+#define IS_IMA(inode)          ((inode)->i_flags & S_IMA)
+#define IS_AUTOMOUNT(inode)    ((inode)->i_flags & S_AUTOMOUNT)
+#define IS_NOSEC(inode)                ((inode)->i_flags & S_NOSEC)
+
+/*
  * Inode state bits.  Protected by inode->i_lock
  *
  * Three bits determine the dirty state of the inode, I_DIRTY_SYNC,
@@ -1688,6 +1807,11 @@ int sync_inode_metadata(struct inode *inode, int wait);
 struct file_system_type {
        const char *name;
        int fs_flags;
+#define FS_REQUIRES_DEV                1 
+#define FS_BINARY_MOUNTDATA    2
+#define FS_HAS_SUBTYPE         4
+#define FS_REVAL_DOT           16384   /* Check the paths ".", ".." for staleness */
+#define FS_RENAME_DOES_D_MOVE  32768   /* FS will handle d_move() during rename() internally. */
        struct dentry *(*mount) (struct file_system_type *, int,
                       const char *, void *);
        void (*kill_sb) (struct super_block *);
@@ -1923,7 +2047,6 @@ extern void unregister_blkdev(unsigned int, const char *);
 extern struct block_device *bdget(dev_t);
 extern struct block_device *bdgrab(struct block_device *bdev);
 extern void bd_set_size(struct block_device *, loff_t size);
-extern sector_t blkdev_max_block(struct block_device *bdev);
 extern void bd_forget(struct inode *inode);
 extern void bdput(struct block_device *);
 extern void invalidate_bdev(struct block_device *);
@@ -2253,8 +2376,6 @@ extern int generic_segment_checks(const struct iovec *iov,
                unsigned long *nr_segs, size_t *count, int access_flags);
 
 /* fs/block_dev.c */
-extern ssize_t blkdev_aio_read(struct kiocb *iocb, const struct iovec *iov,
-                              unsigned long nr_segs, loff_t pos);
 extern ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov,
                                unsigned long nr_segs, loff_t pos);
 extern int blkdev_fsync(struct file *filp, loff_t start, loff_t end,
index 02c1c97..d0a7967 100644 (file)
@@ -31,6 +31,7 @@ struct vm_area_struct;
 #define ___GFP_THISNODE                0x40000u
 #define ___GFP_RECLAIMABLE     0x80000u
 #define ___GFP_NOTRACK         0x200000u
+#define ___GFP_NO_KSWAPD       0x400000u
 #define ___GFP_OTHER_NODE      0x800000u
 #define ___GFP_WRITE           0x1000000u
 
@@ -85,6 +86,7 @@ struct vm_area_struct;
 #define __GFP_RECLAIMABLE ((__force gfp_t)___GFP_RECLAIMABLE) /* Page is reclaimable */
 #define __GFP_NOTRACK  ((__force gfp_t)___GFP_NOTRACK)  /* Don't track with kmemcheck */
 
+#define __GFP_NO_KSWAPD        ((__force gfp_t)___GFP_NO_KSWAPD)
 #define __GFP_OTHER_NODE ((__force gfp_t)___GFP_OTHER_NODE) /* On behalf of other node */
 #define __GFP_WRITE    ((__force gfp_t)___GFP_WRITE)   /* Allocator intends to dirty page */
 
@@ -114,7 +116,8 @@ struct vm_area_struct;
                                 __GFP_MOVABLE)
 #define GFP_IOFS       (__GFP_IO | __GFP_FS)
 #define GFP_TRANSHUGE  (GFP_HIGHUSER_MOVABLE | __GFP_COMP | \
-                        __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN)
+                        __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN | \
+                        __GFP_NO_KSWAPD)
 
 #ifdef CONFIG_NUMA
 #define GFP_THISNODE   (__GFP_THISNODE | __GFP_NOWARN | __GFP_NORETRY)
index 2e31e8b..bfe6656 100644 (file)
@@ -72,9 +72,9 @@ static inline int irq_to_gpio(unsigned int irq)
        return -EINVAL;
 }
 
-#endif
+#endif /* ! CONFIG_ARCH_HAVE_CUSTOM_GPIO_H */
 
-#else
+#else /* ! CONFIG_GENERIC_GPIO */
 
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -231,6 +231,21 @@ static inline int irq_to_gpio(unsigned irq)
        return -EINVAL;
 }
 
-#endif
+static inline int
+gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
+                      unsigned int gpio_offset, unsigned int pin_offset,
+                      unsigned int npins)
+{
+       WARN_ON(1);
+       return -EINVAL;
+}
+
+static inline void
+gpiochip_remove_pin_ranges(struct gpio_chip *chip)
+{
+       WARN_ON(1);
+}
+
+#endif /* ! CONFIG_GENERIC_GPIO */
 
 #endif /* __LINUX_GPIO_H */
diff --git a/include/linux/hashtable.h b/include/linux/hashtable.h
new file mode 100644 (file)
index 0000000..227c624
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * Statically sized hash table implementation
+ * (C) 2012  Sasha Levin <levinsasha928@gmail.com>
+ */
+
+#ifndef _LINUX_HASHTABLE_H
+#define _LINUX_HASHTABLE_H
+
+#include <linux/list.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/hash.h>
+#include <linux/rculist.h>
+
+#define DEFINE_HASHTABLE(name, bits)                                           \
+       struct hlist_head name[1 << (bits)] =                                   \
+                       { [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT }
+
+#define DECLARE_HASHTABLE(name, bits)                                          \
+       struct hlist_head name[1 << (bits)]
+
+#define HASH_SIZE(name) (ARRAY_SIZE(name))
+#define HASH_BITS(name) ilog2(HASH_SIZE(name))
+
+/* Use hash_32 when possible to allow for fast 32bit hashing in 64bit kernels. */
+#define hash_min(val, bits)                                                    \
+       (sizeof(val) <= 4 ? hash_32(val, bits) : hash_long(val, bits))
+
+static inline void __hash_init(struct hlist_head *ht, unsigned int sz)
+{
+       unsigned int i;
+
+       for (i = 0; i < sz; i++)
+               INIT_HLIST_HEAD(&ht[i]);
+}
+
+/**
+ * hash_init - initialize a hash table
+ * @hashtable: hashtable to be initialized
+ *
+ * Calculates the size of the hashtable from the given parameter, otherwise
+ * same as hash_init_size.
+ *
+ * This has to be a macro since HASH_BITS() will not work on pointers since
+ * it calculates the size during preprocessing.
+ */
+#define hash_init(hashtable) __hash_init(hashtable, HASH_SIZE(hashtable))
+
+/**
+ * hash_add - add an object to a hashtable
+ * @hashtable: hashtable to add to
+ * @node: the &struct hlist_node of the object to be added
+ * @key: the key of the object to be added
+ */
+#define hash_add(hashtable, node, key)                                         \
+       hlist_add_head(node, &hashtable[hash_min(key, HASH_BITS(hashtable))])
+
+/**
+ * hash_add_rcu - add an object to a rcu enabled hashtable
+ * @hashtable: hashtable to add to
+ * @node: the &struct hlist_node of the object to be added
+ * @key: the key of the object to be added
+ */
+#define hash_add_rcu(hashtable, node, key)                                     \
+       hlist_add_head_rcu(node, &hashtable[hash_min(key, HASH_BITS(hashtable))])
+
+/**
+ * hash_hashed - check whether an object is in any hashtable
+ * @node: the &struct hlist_node of the object to be checked
+ */
+static inline bool hash_hashed(struct hlist_node *node)
+{
+       return !hlist_unhashed(node);
+}
+
+static inline bool __hash_empty(struct hlist_head *ht, unsigned int sz)
+{
+       unsigned int i;
+
+       for (i = 0; i < sz; i++)
+               if (!hlist_empty(&ht[i]))
+                       return false;
+
+       return true;
+}
+
+/**
+ * hash_empty - check whether a hashtable is empty
+ * @hashtable: hashtable to check
+ *
+ * This has to be a macro since HASH_BITS() will not work on pointers since
+ * it calculates the size during preprocessing.
+ */
+#define hash_empty(hashtable) __hash_empty(hashtable, HASH_SIZE(hashtable))
+
+/**
+ * hash_del - remove an object from a hashtable
+ * @node: &struct hlist_node of the object to remove
+ */
+static inline void hash_del(struct hlist_node *node)
+{
+       hlist_del_init(node);
+}
+
+/**
+ * hash_del_rcu - remove an object from a rcu enabled hashtable
+ * @node: &struct hlist_node of the object to remove
+ */
+static inline void hash_del_rcu(struct hlist_node *node)
+{
+       hlist_del_init_rcu(node);
+}
+
+/**
+ * hash_for_each - iterate over a hashtable
+ * @name: hashtable to iterate
+ * @bkt: integer to use as bucket loop cursor
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @obj: the type * to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ */
+#define hash_for_each(name, bkt, node, obj, member)                            \
+       for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\
+               hlist_for_each_entry(obj, node, &name[bkt], member)
+
+/**
+ * hash_for_each_rcu - iterate over a rcu enabled hashtable
+ * @name: hashtable to iterate
+ * @bkt: integer to use as bucket loop cursor
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @obj: the type * to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ */
+#define hash_for_each_rcu(name, bkt, node, obj, member)                                \
+       for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\
+               hlist_for_each_entry_rcu(obj, node, &name[bkt], member)
+
+/**
+ * hash_for_each_safe - iterate over a hashtable safe against removal of
+ * hash entry
+ * @name: hashtable to iterate
+ * @bkt: integer to use as bucket loop cursor
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @tmp: a &struct used for temporary storage
+ * @obj: the type * to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ */
+#define hash_for_each_safe(name, bkt, node, tmp, obj, member)                  \
+       for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\
+               hlist_for_each_entry_safe(obj, node, tmp, &name[bkt], member)
+
+/**
+ * hash_for_each_possible - iterate over all possible objects hashing to the
+ * same bucket
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each entry
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ * @key: the key of the objects to iterate over
+ */
+#define hash_for_each_possible(name, obj, node, member, key)                   \
+       hlist_for_each_entry(obj, node, &name[hash_min(key, HASH_BITS(name))], member)
+
+/**
+ * hash_for_each_possible_rcu - iterate over all possible objects hashing to the
+ * same bucket in an rcu enabled hashtable
+ * in a rcu enabled hashtable
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each entry
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ * @key: the key of the objects to iterate over
+ */
+#define hash_for_each_possible_rcu(name, obj, node, member, key)               \
+       hlist_for_each_entry_rcu(obj, node, &name[hash_min(key, HASH_BITS(name))], member)
+
+/**
+ * hash_for_each_possible_safe - iterate over all possible objects hashing to the
+ * same bucket safe against removals
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each entry
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @tmp: a &struct used for temporary storage
+ * @member: the name of the hlist_node within the struct
+ * @key: the key of the objects to iterate over
+ */
+#define hash_for_each_possible_safe(name, obj, node, tmp, member, key)         \
+       hlist_for_each_entry_safe(obj, node, tmp,                               \
+               &name[hash_min(key, HASH_BITS(name))], member)
+
+
+#endif
index 271a770..e69de29 100644 (file)
@@ -1 +0,0 @@
-header-y += hsi_char.h
index 6ae9c63..0464c85 100644 (file)
@@ -1,35 +1,8 @@
 #ifndef _LINUX_HW_BREAKPOINT_H
 #define _LINUX_HW_BREAKPOINT_H
 
-enum {
-       HW_BREAKPOINT_LEN_1 = 1,
-       HW_BREAKPOINT_LEN_2 = 2,
-       HW_BREAKPOINT_LEN_4 = 4,
-       HW_BREAKPOINT_LEN_8 = 8,
-};
-
-enum {
-       HW_BREAKPOINT_EMPTY     = 0,
-       HW_BREAKPOINT_R         = 1,
-       HW_BREAKPOINT_W         = 2,
-       HW_BREAKPOINT_RW        = HW_BREAKPOINT_R | HW_BREAKPOINT_W,
-       HW_BREAKPOINT_X         = 4,
-       HW_BREAKPOINT_INVALID   = HW_BREAKPOINT_RW | HW_BREAKPOINT_X,
-};
-
-enum bp_type_idx {
-       TYPE_INST       = 0,
-#ifdef CONFIG_HAVE_MIXED_BREAKPOINTS_REGS
-       TYPE_DATA       = 0,
-#else
-       TYPE_DATA       = 1,
-#endif
-       TYPE_MAX
-};
-
-#ifdef __KERNEL__
-
 #include <linux/perf_event.h>
+#include <uapi/linux/hw_breakpoint.h>
 
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
 
@@ -151,6 +124,4 @@ static inline struct arch_hw_breakpoint *counter_arch_bp(struct perf_event *bp)
 }
 
 #endif /* CONFIG_HAVE_HW_BREAKPOINT */
-#endif /* __KERNEL__ */
-
 #endif /* _LINUX_HW_BREAKPOINT_H */
index df804ba..92a0dc7 100644 (file)
@@ -34,6 +34,7 @@ struct omap_i2c_bus_platform_data {
        u32             clkrate;
        u32             rev;
        u32             flags;
+       void            (*set_mpu_wkup_lat)(struct device *dev, long set);
 };
 
 #endif
index 800de22..d0c4db7 100644 (file)
@@ -259,6 +259,7 @@ static inline void i2c_set_clientdata(struct i2c_client *dev, void *data)
  * @platform_data: stored in i2c_client.dev.platform_data
  * @archdata: copied into i2c_client.dev.archdata
  * @of_node: pointer to OpenFirmware device node
+ * @acpi_node: ACPI device node
  * @irq: stored in i2c_client.irq
  *
  * I2C doesn't actually support hardware probing, although controllers and
@@ -279,6 +280,7 @@ struct i2c_board_info {
        void            *platform_data;
        struct dev_archdata     *archdata;
        struct device_node *of_node;
+       struct acpi_dev_node acpi_node;
        int             irq;
 };
 
@@ -501,4 +503,11 @@ static inline int i2c_adapter_id(struct i2c_adapter *adap)
                        i2c_del_driver)
 
 #endif /* I2C */
+
+#if IS_ENABLED(CONFIG_ACPI_I2C)
+extern void acpi_i2c_register_devices(struct i2c_adapter *adap);
+#else
+static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) {}
+#endif
+
 #endif /* _LINUX_I2C_H */
index c0ae76a..7806c24 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_ */
diff --git a/include/linux/isdn/Kbuild b/include/linux/isdn/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index a123b13..7d8dfc7 100644 (file)
@@ -701,6 +701,13 @@ static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { }
 #define COMPACTION_BUILD 0
 #endif
 
+/* This helps us to avoid #ifdef CONFIG_SYMBOL_PREFIX */
+#ifdef CONFIG_SYMBOL_PREFIX
+#define SYMBOL_PREFIX CONFIG_SYMBOL_PREFIX
+#else
+#define SYMBOL_PREFIX ""
+#endif
+
 /* Rebuild everything on CONFIG_FTRACE_MCOUNT_RECORD */
 #ifdef CONFIG_FTRACE_MCOUNT_RECORD
 # define REBUILD_DUE_TO_FTRACE_MCOUNT_RECORD
index 93bfc9f..ecc5543 100644 (file)
  */
 #define KVM_MEMSLOT_INVALID    (1UL << 16)
 
-/*
- * If we support unaligned MMIO, at most one fragment will be split into two:
- */
-#ifdef KVM_UNALIGNED_MMIO
-#  define KVM_EXTRA_MMIO_FRAGMENTS 1
-#else
-#  define KVM_EXTRA_MMIO_FRAGMENTS 0
-#endif
-
-#define KVM_USER_MMIO_SIZE 8
-
-#define KVM_MAX_MMIO_FRAGMENTS \
-       (KVM_MMIO_SIZE / KVM_USER_MMIO_SIZE + KVM_EXTRA_MMIO_FRAGMENTS)
+/* Two fragments for cross MMIO pages. */
+#define KVM_MAX_MMIO_FRAGMENTS 2
 
 /*
  * For the normal pfn, the highest 12 bits should be zero,
index 569d67d..d452ee1 100644 (file)
@@ -57,6 +57,7 @@ int memblock_add(phys_addr_t base, phys_addr_t size);
 int memblock_remove(phys_addr_t base, phys_addr_t size);
 int memblock_free(phys_addr_t base, phys_addr_t size);
 int memblock_reserve(phys_addr_t base, phys_addr_t size);
+void memblock_trim_memory(phys_addr_t align);
 
 #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
 void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn,
index e5ccb9d..dbd2127 100644 (file)
@@ -82,16 +82,6 @@ static inline void mpol_cond_put(struct mempolicy *pol)
                __mpol_put(pol);
 }
 
-extern struct mempolicy *__mpol_cond_copy(struct mempolicy *tompol,
-                                         struct mempolicy *frompol);
-static inline struct mempolicy *mpol_cond_copy(struct mempolicy *tompol,
-                                               struct mempolicy *frompol)
-{
-       if (!frompol)
-               return frompol;
-       return __mpol_cond_copy(tompol, frompol);
-}
-
 extern struct mempolicy *__mpol_dup(struct mempolicy *pol);
 static inline struct mempolicy *mpol_dup(struct mempolicy *pol)
 {
@@ -215,12 +205,6 @@ static inline void mpol_cond_put(struct mempolicy *pol)
 {
 }
 
-static inline struct mempolicy *mpol_cond_copy(struct mempolicy *to,
-                                               struct mempolicy *from)
-{
-       return from;
-}
-
 static inline void mpol_get(struct mempolicy *pol)
 {
 }
index b82f6ee..6ee4247 100644 (file)
@@ -515,7 +515,6 @@ enum romcode_read prcmu_get_rc_p2a(void);
 enum ap_pwrst prcmu_get_xp70_current_state(void);
 bool prcmu_has_arm_maxopp(void);
 struct prcmu_fw_version *prcmu_get_fw_version(void);
-int prcmu_request_ape_opp_100_voltage(bool enable);
 int prcmu_release_usb_wakeup_state(void);
 void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
        struct prcmu_auto_pm_config *idle);
@@ -564,6 +563,7 @@ int db8500_prcmu_set_arm_opp(u8 opp);
 int db8500_prcmu_get_arm_opp(void);
 int db8500_prcmu_set_ape_opp(u8 opp);
 int db8500_prcmu_get_ape_opp(void);
+int db8500_prcmu_request_ape_opp_100_voltage(bool enable);
 int db8500_prcmu_set_ddr_opp(u8 opp);
 int db8500_prcmu_get_ddr_opp(void);
 
@@ -610,7 +610,7 @@ static inline int db8500_prcmu_get_ape_opp(void)
        return APE_100_OPP;
 }
 
-static inline int prcmu_request_ape_opp_100_voltage(bool enable)
+static inline int db8500_prcmu_request_ape_opp_100_voltage(bool enable)
 {
        return 0;
 }
index c410d99..c202d6c 100644 (file)
@@ -336,6 +336,11 @@ static inline int prcmu_get_ape_opp(void)
        return db8500_prcmu_get_ape_opp();
 }
 
+static inline int prcmu_request_ape_opp_100_voltage(bool enable)
+{
+       return db8500_prcmu_request_ape_opp_100_voltage(enable);
+}
+
 static inline void prcmu_system_reset(u16 reset_code)
 {
        return db8500_prcmu_system_reset(reset_code);
@@ -507,6 +512,11 @@ static inline int prcmu_get_ape_opp(void)
        return APE_100_OPP;
 }
 
+static inline int prcmu_request_ape_opp_100_voltage(bool enable)
+{
+       return 0;
+}
+
 static inline int prcmu_set_arm_opp(u8 opp)
 {
        return 0;
index 1d28ae9..fe03b2d 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 fa06804..bcaab4e 100644 (file)
@@ -1684,9 +1684,5 @@ static inline unsigned int debug_guardpage_minorder(void) { return 0; }
 static inline bool page_is_guard(struct page *page) { return false; }
 #endif /* CONFIG_DEBUG_PAGEALLOC */
 
-extern void reset_zone_present_pages(void);
-extern void fixup_zone_present_pages(int nid, unsigned long start_pfn,
-                               unsigned long end_pfn);
-
 #endif /* __KERNEL__ */
 #endif /* _LINUX_MM_H */
diff --git a/include/linux/mmc/Kbuild b/include/linux/mmc/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index 943550d..5c69315 100644 (file)
@@ -85,6 +85,7 @@ struct mmc_ext_csd {
        bool                    boot_ro_lockable;
        u8                      raw_exception_status;   /* 53 */
        u8                      raw_partition_support;  /* 160 */
+       u8                      raw_rpmb_size_mult;     /* 168 */
        u8                      raw_erased_mem_count;   /* 181 */
        u8                      raw_ext_csd_structure;  /* 194 */
        u8                      raw_card_type;          /* 196 */
@@ -206,6 +207,7 @@ struct mmc_part {
 #define MMC_BLK_DATA_AREA_MAIN (1<<0)
 #define MMC_BLK_DATA_AREA_BOOT (1<<1)
 #define MMC_BLK_DATA_AREA_GP   (1<<2)
+#define MMC_BLK_DATA_AREA_RPMB (1<<3)
 };
 
 /*
index 9b9cdaf..5bf7c22 100644 (file)
@@ -170,6 +170,8 @@ extern int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from,
 extern unsigned int mmc_calc_max_discard(struct mmc_card *card);
 
 extern int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen);
+extern int mmc_set_blockcount(struct mmc_card *card, unsigned int blockcount,
+                             bool is_rel_write);
 extern int mmc_hw_reset(struct mmc_host *host);
 extern int mmc_hw_reset_check(struct mmc_host *host);
 extern int mmc_can_reset(struct mmc_card *card);
index 7c6a113..34be4f4 100644 (file)
@@ -137,7 +137,7 @@ struct dw_mci {
 
        dma_addr_t              sg_dma;
        void                    *sg_cpu;
-       struct dw_mci_dma_ops   *dma_ops;
+       const struct dw_mci_dma_ops     *dma_ops;
 #ifdef CONFIG_MMC_DW_IDMAC
        unsigned int            ring_size;
 #else
@@ -162,7 +162,7 @@ struct dw_mci {
        u16                     data_offset;
        struct device           *dev;
        struct dw_mci_board     *pdata;
-       struct dw_mci_drv_data  *drv_data;
+       const struct dw_mci_drv_data    *drv_data;
        void                    *priv;
        struct clk              *biu_clk;
        struct clk              *ciu_clk;
@@ -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 */
@@ -229,8 +229,9 @@ struct dw_mci_board {
        u32 quirks; /* Workaround / Quirk flags */
        unsigned int bus_hz; /* Clock speed at the cclk_in pad */
 
-       unsigned int caps;      /* Capabilities */
-       unsigned int caps2;     /* More capabilities */
+       u32 caps;       /* Capabilities */
+       u32 caps2;      /* More capabilities */
+       u32 pm_caps;    /* PM capabilities */
        /*
         * Override fifo depth. If 0, autodetect it from the FIFOTH register,
         * but note that this may not be reliable after a bootloader has used
index 7abb0e1..61a10c1 100644 (file)
@@ -53,12 +53,12 @@ struct mmc_ios {
 #define MMC_TIMING_LEGACY      0
 #define MMC_TIMING_MMC_HS      1
 #define MMC_TIMING_SD_HS       2
-#define MMC_TIMING_UHS_SDR12   MMC_TIMING_LEGACY
-#define MMC_TIMING_UHS_SDR25   MMC_TIMING_SD_HS
-#define MMC_TIMING_UHS_SDR50   3
-#define MMC_TIMING_UHS_SDR104  4
-#define MMC_TIMING_UHS_DDR50   5
-#define MMC_TIMING_MMC_HS200   6
+#define MMC_TIMING_UHS_SDR12   3
+#define MMC_TIMING_UHS_SDR25   4
+#define MMC_TIMING_UHS_SDR50   5
+#define MMC_TIMING_UHS_SDR104  6
+#define MMC_TIMING_UHS_DDR50   7
+#define MMC_TIMING_MMC_HS200   8
 
 #define MMC_SDR_MODE           0
 #define MMC_1_2V_DDR_MODE      1
@@ -136,6 +136,7 @@ struct mmc_host_ops {
        void    (*enable_preset_value)(struct mmc_host *host, bool enable);
        int     (*select_drive_strength)(unsigned int max_dtr, int host_drv, int card_drv);
        void    (*hw_reset)(struct mmc_host *host);
+       void    (*card_event)(struct mmc_host *host);
 };
 
 struct mmc_card;
@@ -211,7 +212,7 @@ struct mmc_host {
 #define MMC_VDD_34_35          0x00400000      /* VDD voltage 3.4 ~ 3.5 */
 #define MMC_VDD_35_36          0x00800000      /* VDD voltage 3.5 ~ 3.6 */
 
-       unsigned long           caps;           /* Host capabilities */
+       u32                     caps;           /* Host capabilities */
 
 #define MMC_CAP_4_BIT_DATA     (1 << 0)        /* Can the host do 4 bit transfers */
 #define MMC_CAP_MMC_HIGHSPEED  (1 << 1)        /* Can do MMC high-speed timing */
@@ -241,7 +242,7 @@ struct mmc_host {
 #define MMC_CAP_CMD23          (1 << 30)       /* CMD23 supported. */
 #define MMC_CAP_HW_RESET       (1 << 31)       /* Hardware reset */
 
-       unsigned int            caps2;          /* More host capabilities */
+       u32                     caps2;          /* More host capabilities */
 
 #define MMC_CAP2_BOOTPART_NOACC        (1 << 0)        /* Boot partition no access */
 #define MMC_CAP2_CACHE_CTRL    (1 << 1)        /* Allow cache control */
index 01e4b39..94d532e 100644 (file)
@@ -286,6 +286,7 @@ struct _mmc_csd {
 #define EXT_CSD_BKOPS_START            164     /* W */
 #define EXT_CSD_SANITIZE_START         165     /* W */
 #define EXT_CSD_WR_REL_PARAM           166     /* RO */
+#define EXT_CSD_RPMB_MULT              168     /* RO */
 #define EXT_CSD_BOOT_WP                        173     /* R/W */
 #define EXT_CSD_ERASE_GROUP_DEF                175     /* R/W */
 #define EXT_CSD_PART_CONFIG            179     /* R/W */
@@ -339,6 +340,7 @@ struct _mmc_csd {
 
 #define EXT_CSD_PART_CONFIG_ACC_MASK   (0x7)
 #define EXT_CSD_PART_CONFIG_ACC_BOOT0  (0x1)
+#define EXT_CSD_PART_CONFIG_ACC_RPMB   (0x3)
 #define EXT_CSD_PART_CONFIG_ACC_GP0    (0x4)
 
 #define EXT_CSD_PART_SUPPORT_PART_EN   (0x1)
diff --git a/include/linux/mmc/mxs-mmc.h b/include/linux/mmc/mxs-mmc.h
deleted file mode 100644 (file)
index 7c2ad3a..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2011 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 __LINUX_MMC_MXS_MMC_H__
-#define __LINUX_MMC_MXS_MMC_H__
-
-struct mxs_mmc_platform_data {
-       int wp_gpio;    /* write protect pin */
-       unsigned int flags;
-#define SLOTF_4_BIT_CAPABLE    (1 << 0)
-#define SLOTF_8_BIT_CAPABLE    (1 << 1)
-};
-
-#endif /* __LINUX_MMC_MXS_MMC_H__ */
index fa8529a..4bbc330 100644 (file)
@@ -91,6 +91,9 @@ struct sdhci_host {
        unsigned int quirks2;   /* More deviations from spec. */
 
 #define SDHCI_QUIRK2_HOST_OFF_CARD_ON                  (1<<0)
+#define SDHCI_QUIRK2_HOST_NO_CMD23                     (1<<1)
+/* The system physically doesn't support 1.8v, even if the host does */
+#define SDHCI_QUIRK2_NO_1_8_V                          (1<<2)
 
        int irq;                /* Device IRQ */
        void __iomem *ioaddr;   /* Mapped address */
@@ -157,8 +160,8 @@ struct sdhci_host {
 
        struct timer_list timer;        /* Timer for timeouts */
 
-       unsigned int caps;      /* Alternative CAPABILITY_0 */
-       unsigned int caps1;     /* Alternative CAPABILITY_1 */
+       u32 caps;               /* Alternative CAPABILITY_0 */
+       u32 caps1;              /* Alternative CAPABILITY_1 */
 
        unsigned int            ocr_avail_sdio; /* OCR bit masks */
        unsigned int            ocr_avail_sd;
index 50aaca8..a23923b 100644 (file)
@@ -752,7 +752,7 @@ extern int init_currently_empty_zone(struct zone *zone, unsigned long start_pfn,
                                     unsigned long size,
                                     enum memmap_context context);
 
-extern void lruvec_init(struct lruvec *lruvec, struct zone *zone);
+extern void lruvec_init(struct lruvec *lruvec);
 
 static inline struct zone *lruvec_zone(struct lruvec *lruvec)
 {
index f8eda02..a848ffc 100644 (file)
@@ -1488,6 +1488,9 @@ struct napi_gro_cb {
 
        /* Used in ipv6_gro_receive() */
        int     proto;
+
+       /* used in skb_gro_receive() slow path */
+       struct sk_buff *last;
 };
 
 #define NAPI_GRO_CB(skb) ((struct napi_gro_cb *)(skb)->cb)
diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild
deleted file mode 100644 (file)
index b332202..0000000
+++ /dev/null
@@ -1 +0,0 @@
-header-y += ipset/
diff --git a/include/linux/netfilter/ipset/Kbuild b/include/linux/netfilter/ipset/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/include/linux/netfilter_arp/Kbuild b/include/linux/netfilter_arp/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/include/linux/netfilter_bridge/Kbuild b/include/linux/netfilter_bridge/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/include/linux/netfilter_ipv4/Kbuild b/include/linux/netfilter_ipv4/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/include/linux/netfilter_ipv6/Kbuild b/include/linux/netfilter_ipv6/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/include/linux/nfsd/Kbuild b/include/linux/nfsd/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index 72843b7..60053bd 100644 (file)
@@ -46,7 +46,7 @@ struct device_node {
        const char *name;
        const char *type;
        phandle phandle;
-       char    *full_name;
+       const char *full_name;
 
        struct  property *properties;
        struct  property *deadprops;    /* removed properties */
@@ -60,7 +60,7 @@ struct device_node {
        unsigned long _flags;
        void    *data;
 #if defined(CONFIG_SPARC)
-       char    *path_component_name;
+       const char *path_component_name;
        unsigned int unique_id;
        struct of_irq_controller *irq_trans;
 #endif
@@ -88,14 +88,14 @@ static inline void of_node_put(struct device_node *node) { }
 #ifdef CONFIG_OF
 
 /* Pointer for first entry in chain of all nodes. */
-extern struct device_node *allnodes;
+extern struct device_node *of_allnodes;
 extern struct device_node *of_chosen;
 extern struct device_node *of_aliases;
 extern rwlock_t devtree_lock;
 
 static inline bool of_have_populated_dt(void)
 {
-       return allnodes != NULL;
+       return of_allnodes != NULL;
 }
 
 static inline bool of_node_is_root(const struct device_node *node)
@@ -179,11 +179,22 @@ extern struct device_node *of_find_compatible_node(struct device_node *from,
 #define for_each_compatible_node(dn, type, compatible) \
        for (dn = of_find_compatible_node(NULL, type, compatible); dn; \
             dn = of_find_compatible_node(dn, type, compatible))
-extern struct device_node *of_find_matching_node(struct device_node *from,
-       const struct of_device_id *matches);
+extern struct device_node *of_find_matching_node_and_match(
+       struct device_node *from,
+       const struct of_device_id *matches,
+       const struct of_device_id **match);
+static inline struct device_node *of_find_matching_node(
+       struct device_node *from,
+       const struct of_device_id *matches)
+{
+       return of_find_matching_node_and_match(from, matches, NULL);
+}
 #define for_each_matching_node(dn, matches) \
        for (dn = of_find_matching_node(NULL, matches); dn; \
             dn = of_find_matching_node(dn, matches))
+#define for_each_matching_node_and_match(dn, matches, match) \
+       for (dn = of_find_matching_node_and_match(NULL, matches, match); \
+            dn; dn = of_find_matching_node_and_match(dn, matches, match))
 extern struct device_node *of_find_node_by_path(const char *path);
 extern struct device_node *of_find_node_by_phandle(phandle handle);
 extern struct device_node *of_get_parent(const struct device_node *node);
@@ -223,6 +234,10 @@ extern struct device_node *of_find_node_with_property(
 extern struct property *of_find_property(const struct device_node *np,
                                         const char *name,
                                         int *lenp);
+extern int of_property_read_u8_array(const struct device_node *np,
+                       const char *propname, u8 *out_values, size_t sz);
+extern int of_property_read_u16_array(const struct device_node *np,
+                       const char *propname, u16 *out_values, size_t sz);
 extern int of_property_read_u32_array(const struct device_node *np,
                                      const char *propname,
                                      u32 *out_values,
@@ -255,7 +270,7 @@ extern int of_n_size_cells(struct device_node *np);
 extern const struct of_device_id *of_match_node(
        const struct of_device_id *matches, const struct device_node *node);
 extern int of_modalias_node(struct device_node *node, char *modalias, int len);
-extern struct device_node *of_parse_phandle(struct device_node *np,
+extern struct device_node *of_parse_phandle(const struct device_node *np,
                                            const char *phandle_name,
                                            int index);
 extern int of_parse_phandle_with_args(struct device_node *np,
@@ -331,6 +346,13 @@ static inline bool of_have_populated_dt(void)
 #define for_each_child_of_node(parent, child) \
        while (0)
 
+static inline struct device_node *of_get_child_by_name(
+                                       const struct device_node *node,
+                                       const char *name)
+{
+       return NULL;
+}
+
 static inline int of_get_child_count(const struct device_node *np)
 {
        return 0;
@@ -357,6 +379,18 @@ static inline struct device_node *of_find_compatible_node(
        return NULL;
 }
 
+static inline int of_property_read_u8_array(const struct device_node *np,
+                       const char *propname, u8 *out_values, size_t sz)
+{
+       return -ENOSYS;
+}
+
+static inline int of_property_read_u16_array(const struct device_node *np,
+                       const char *propname, u16 *out_values, size_t sz)
+{
+       return -ENOSYS;
+}
+
 static inline int of_property_read_u32_array(const struct device_node *np,
                                             const char *propname,
                                             u32 *out_values, size_t sz)
@@ -404,7 +438,7 @@ static inline int of_property_match_string(struct device_node *np,
        return -ENOSYS;
 }
 
-static inline struct device_node *of_parse_phandle(struct device_node *np,
+static inline struct device_node *of_parse_phandle(const struct device_node *np,
                                                   const char *phandle_name,
                                                   int index)
 {
@@ -463,6 +497,20 @@ static inline bool of_property_read_bool(const struct device_node *np,
        return prop ? true : false;
 }
 
+static inline int of_property_read_u8(const struct device_node *np,
+                                      const char *propname,
+                                      u8 *out_value)
+{
+       return of_property_read_u8_array(np, propname, out_value, 1);
+}
+
+static inline int of_property_read_u16(const struct device_node *np,
+                                      const char *propname,
+                                      u16 *out_value)
+{
+       return of_property_read_u16_array(np, propname, out_value, 1);
+}
+
 static inline int of_property_read_u32(const struct device_node *np,
                                       const char *propname,
                                       u32 *out_value)
index c3cdc10..0506eb5 100644 (file)
@@ -19,7 +19,7 @@ extern void __iomem *of_iomap(struct device_node *device, int index);
  * the address space flags too. The PCI version uses a BAR number
  * instead of an absolute index
  */
-extern const u32 *of_get_address(struct device_node *dev, int index,
+extern const __be32 *of_get_address(struct device_node *dev, int index,
                           u64 *size, unsigned int *flags);
 
 #ifndef pci_address_to_pio
@@ -28,11 +28,13 @@ static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; }
 #endif
 
 #else /* CONFIG_OF_ADDRESS */
+#ifndef of_address_to_resource
 static inline int of_address_to_resource(struct device_node *dev, int index,
                                         struct resource *r)
 {
        return -EINVAL;
 }
+#endif
 static inline struct device_node *of_find_matching_node_by_address(
                                        struct device_node *from,
                                        const struct of_device_id *matches,
@@ -40,11 +42,13 @@ static inline struct device_node *of_find_matching_node_by_address(
 {
        return NULL;
 }
+#ifndef of_iomap
 static inline void __iomem *of_iomap(struct device_node *device, int index)
 {
        return NULL;
 }
-static inline const u32 *of_get_address(struct device_node *dev, int index,
+#endif
+static inline const __be32 *of_get_address(struct device_node *dev, int index,
                                        u64 *size, unsigned int *flags)
 {
        return NULL;
index b8e2411..535cecf 100644 (file)
@@ -58,8 +58,8 @@ static inline int of_irq_map_oldworld(struct device_node *device, int index,
 #endif /* CONFIG_PPC32 && CONFIG_PPC_PMAC */
 
 
-extern int of_irq_map_raw(struct device_node *parent, const u32 *intspec,
-                         u32 ointsize, const u32 *addr,
+extern int of_irq_map_raw(struct device_node *parent, const __be32 *intspec,
+                         u32 ointsize, const __be32 *addr,
                          struct of_irq *out_irq);
 extern int of_irq_map_one(struct device_node *device, int index,
                          struct of_irq *out_irq);
index cf80f7e..bd1e860 100644 (file)
@@ -12,34 +12,27 @@ struct percpu_rw_semaphore {
        struct mutex mtx;
 };
 
+#define light_mb()     barrier()
+#define heavy_mb()     synchronize_sched_expedited()
+
 static inline void percpu_down_read(struct percpu_rw_semaphore *p)
 {
-       rcu_read_lock();
+       rcu_read_lock_sched();
        if (unlikely(p->locked)) {
-               rcu_read_unlock();
+               rcu_read_unlock_sched();
                mutex_lock(&p->mtx);
                this_cpu_inc(*p->counters);
                mutex_unlock(&p->mtx);
                return;
        }
        this_cpu_inc(*p->counters);
-       rcu_read_unlock();
+       rcu_read_unlock_sched();
+       light_mb(); /* A, between read of p->locked and read of data, paired with D */
 }
 
 static inline void percpu_up_read(struct percpu_rw_semaphore *p)
 {
-       /*
-        * On X86, write operation in this_cpu_dec serves as a memory unlock
-        * barrier (i.e. memory accesses may be moved before the write, but
-        * no memory accesses are moved past the write).
-        * On other architectures this may not be the case, so we need smp_mb()
-        * there.
-        */
-#if defined(CONFIG_X86) && (!defined(CONFIG_X86_PPRO_FENCE) && !defined(CONFIG_X86_OOSTORE))
-       barrier();
-#else
-       smp_mb();
-#endif
+       light_mb(); /* B, between read of the data and write to p->counter, paired with C */
        this_cpu_dec(*p->counters);
 }
 
@@ -58,14 +51,15 @@ static inline void percpu_down_write(struct percpu_rw_semaphore *p)
 {
        mutex_lock(&p->mtx);
        p->locked = true;
-       synchronize_rcu();
+       synchronize_sched_expedited(); /* make sure that all readers exit the rcu_read_lock_sched region */
        while (__percpu_count(p->counters))
                msleep(1);
-       smp_rmb(); /* paired with smp_mb() in percpu_sem_up_read() */
+       heavy_mb(); /* C, between read of p->counter and write to data, paired with B */
 }
 
 static inline void percpu_up_write(struct percpu_rw_semaphore *p)
 {
+       heavy_mb(); /* D, between write to data and write to p->locked, paired with A */
        p->locked = false;
        mutex_unlock(&p->mtx);
 }
index 2e90235..6bfb2fa 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 00474b0..65e3e87 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>
index 4f0abb9..47a1bdd 100644 (file)
  * @PIN_CONFIG_DRIVE_OPEN_SOURCE: the pin will be driven with open source
  *     (open emitter). Sending this config will enabale open drain mode, the
  *     argument is ignored.
+ * @PIN_CONFIG_INPUT_SCHMITT_DISABLE: disable schmitt-trigger mode on the pin.
  * @PIN_CONFIG_INPUT_SCHMITT: this will configure an input pin to run in
  *     schmitt-trigger mode. If the schmitt-trigger has adjustable hysteresis,
  *     the threshold value is given on a custom format as argument when
- *     setting pins to this mode. The argument zero turns the schmitt trigger
- *     off.
+ *     setting pins to this mode.
  * @PIN_CONFIG_INPUT_DEBOUNCE: this will configure the pin to debounce mode,
  *     which means it will wait for signals to settle when reading inputs. The
  *     argument gives the debounce time on a custom format. Setting the
@@ -74,6 +74,7 @@ enum pin_config_param {
        PIN_CONFIG_DRIVE_PUSH_PULL,
        PIN_CONFIG_DRIVE_OPEN_DRAIN,
        PIN_CONFIG_DRIVE_OPEN_SOURCE,
+       PIN_CONFIG_INPUT_SCHMITT_DISABLE,
        PIN_CONFIG_INPUT_SCHMITT,
        PIN_CONFIG_INPUT_DEBOUNCE,
        PIN_CONFIG_POWER_SOURCE,
index 7d087f0..04d6700 100644 (file)
@@ -134,6 +134,25 @@ extern void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev,
 extern void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev,
                                struct pinctrl_gpio_range *ranges,
                                unsigned nranges);
+extern void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
+                               struct pinctrl_gpio_range *range);
+
+extern struct pinctrl_dev *pinctrl_find_and_add_gpio_range(const char *devname,
+               struct pinctrl_gpio_range *range);
+extern struct pinctrl_gpio_range *
+pinctrl_find_gpio_range_from_pin(struct pinctrl_dev *pctldev,
+                                unsigned int pin);
+
+#ifdef CONFIG_OF
+extern struct pinctrl_dev *of_pinctrl_get(struct device_node *np);
+#else
+static inline
+struct pinctrl_dev *of_pinctrl_get(struct device_node *np)
+{
+       return NULL;
+}
+#endif /* CONFIG_OF */
+
 extern const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev);
 extern void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev);
 #else
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 83fe9c2..280edac 100644 (file)
@@ -1 +1,3 @@
 void integrator_clk_init(bool is_cp);
+void integrator_impd1_clk_init(void __iomem *base, unsigned int id);
+void integrator_impd1_clk_exit(unsigned int id);
diff --git a/include/linux/platform_data/omap_ocp2scp.h b/include/linux/platform_data/omap_ocp2scp.h
new file mode 100644 (file)
index 0000000..5c6c393
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * omap_ocp2scp.h -- ocp2scp header file
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.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.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * 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 __DRIVERS_OMAP_OCP2SCP_H
+#define __DRIVERS_OMAP_OCP2SCP_H
+
+struct omap_ocp2scp_dev {
+       const char                      *drv_name;
+       struct resource                 *res;
+};
+
+struct omap_ocp2scp_platform_data {
+       int                             dev_cnt;
+       struct omap_ocp2scp_dev         **devices;
+};
+#endif /* __DRIVERS_OMAP_OCP2SCP_H */
index 30dea25..dfbc65d 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;
 };
 
 #endif /* __MACH_U300_GPIO_U300_H */
similarity index 66%
rename from arch/arm/plat-nomadik/include/plat/pincfg.h
rename to include/linux/platform_data/pinctrl-nomadik.h
index 3b8ec60..f73b2f0 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 59acd98..27d3156 100644 (file)
@@ -38,6 +38,7 @@
  * @max_speed: the maximum speed supported
  * @host_caps: Standard MMC host capabilities bit field.
  * @quirks: quirks of platfrom
+ * @quirks2: quirks2 of platfrom
  * @pm_caps: pm_caps of platfrom
  */
 struct sdhci_pxa_platdata {
@@ -48,9 +49,10 @@ struct sdhci_pxa_platdata {
        unsigned int    ext_cd_gpio;
        bool            ext_cd_gpio_invert;
        unsigned int    max_speed;
-       unsigned int    host_caps;
-       unsigned int    host_caps2;
+       u32             host_caps;
+       u32             host_caps2;
        unsigned int    quirks;
+       unsigned int    quirks2;
        unsigned int    pm_caps;
 };
 
index 5711e95..a9ded9a 100644 (file)
@@ -55,6 +55,7 @@ extern int platform_add_devices(struct platform_device **, int);
 
 struct platform_device_info {
                struct device *parent;
+               struct acpi_dev_node acpi_node;
 
                const char *name;
                int id;
index 007e687..03d7bb1 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 9924ea1..5a95013 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 f2dc6d8..38a9935 100644 (file)
@@ -54,7 +54,8 @@ struct ptp_clock_request {
  * clock operations
  *
  * @adjfreq:  Adjusts the frequency of the hardware clock.
- *            parameter delta: Desired period change in parts per billion.
+ *            parameter delta: Desired frequency offset from nominal frequency
+ *            in parts per billion
  *
  * @adjtime:  Shifts the time of the hardware clock.
  *            parameter delta: Desired change in nanoseconds.
index 2415a64..e69de29 100644 (file)
@@ -1,2 +0,0 @@
-header-y += md_p.h
-header-y += md_u.h
index fb1abb3..358c04b 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 e11ccb4..0a260d8 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 214caa3..2ac60c9 100644 (file)
@@ -24,6 +24,7 @@
 #ifndef _LINUX_RBTREE_AUGMENTED_H
 #define _LINUX_RBTREE_AUGMENTED_H
 
+#include <linux/compiler.h>
 #include <linux/rbtree.h>
 
 /*
index 4187da5..a3e7842 100644 (file)
@@ -275,9 +275,11 @@ struct rio_id_table {
  * struct rio_net - RIO network info
  * @node: Node in global list of RIO networks
  * @devices: List of devices in this network
+ * @switches: List of switches in this netowrk
  * @mports: List of master ports accessing this network
  * @hport: Default port for accessing this network
  * @id: RIO network ID
+ * @destid_table: destID allocation table
  */
 struct rio_net {
        struct list_head node;  /* node in list of networks */
diff --git a/include/linux/spi/Kbuild b/include/linux/spi/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index c64de9d..2f694f3 100644 (file)
@@ -46,8 +46,9 @@ struct ads7846_platform_data {
        u16     debounce_rep;           /* additional consecutive good readings
                                         * required after the first two */
        int     gpio_pendown;           /* the GPIO used to decide the pendown
-                                        * state if get_pendown_state == NULL
-                                        */
+                                        * state if get_pendown_state == NULL */
+       int     gpio_pendown_debounce;  /* platform specific debounce time for
+                                        * the gpio_pendown */
        int     (*get_pendown_state)(void);
        int     (*filter_init)  (const struct ads7846_platform_data *pdata,
                                 void **filter_data);
index d9b0c84..8f721e4 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
diff --git a/include/linux/sunrpc/Kbuild b/include/linux/sunrpc/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/include/linux/tc_act/Kbuild b/include/linux/tc_act/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/include/linux/tc_ematch/Kbuild b/include/linux/tc_ematch/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index 8a7fc4b..60b7aac 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        */
index f37fceb..1a6567b 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 e6f0331..2459457 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 07915a3..10278d1 100644 (file)
@@ -1778,17 +1778,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 b607f35..e69de29 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 a54b825..3d84619 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 */
index d1d732c..9c210f2 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 a843d08..65d0a88 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
diff --git a/include/linux/wimax/Kbuild b/include/linux/wimax/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index 171b957..dc004bc 100644 (file)
@@ -40,14 +40,6 @@ enum adv7604_op_ch_sel {
        ADV7604_OP_CH_SEL_RBG = 5,
 };
 
-/* Primary mode (IO register 0x01, [3:0]) */
-enum adv7604_prim_mode {
-       ADV7604_PRIM_MODE_COMP = 1,
-       ADV7604_PRIM_MODE_RGB = 2,
-       ADV7604_PRIM_MODE_HDMI_COMP = 5,
-       ADV7604_PRIM_MODE_HDMI_GR = 6,
-};
-
 /* Input Color Space (IO register 0x02, [7:4]) */
 enum adv7604_inp_color_space {
        ADV7604_INP_COLOR_SPACE_LIM_RGB = 0,
@@ -103,9 +95,6 @@ struct adv7604_platform_data {
        /* Bus rotation and reordering */
        enum adv7604_op_ch_sel op_ch_sel;
 
-       /* Primary mode */
-       enum adv7604_prim_mode prim_mode;
-
        /* Select output format */
        enum adv7604_op_format_sel op_format_sel;
 
@@ -142,6 +131,16 @@ struct adv7604_platform_data {
        u8 i2c_vdp;
 };
 
+/*
+ * Mode of operation.
+ * This is used as the input argument of the s_routing video op.
+ */
+enum adv7604_mode {
+       ADV7604_MODE_COMP,
+       ADV7604_MODE_GR,
+       ADV7604_MODE_HDMI,
+};
+
 #define V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE  (V4L2_CID_DV_CLASS_BASE + 0x1000)
 #define V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL  (V4L2_CID_DV_CLASS_BASE + 0x1001)
 #define V4L2_CID_ADV_RX_FREE_RUN_COLOR         (V4L2_CID_DV_CLASS_BASE + 0x1002)
diff --git a/include/mtd/Kbuild b/include/mtd/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index 1b49890..7d5b600 100644 (file)
@@ -1218,6 +1218,7 @@ struct cfg80211_deauth_request {
        const u8 *ie;
        size_t ie_len;
        u16 reason_code;
+       bool local_state_change;
 };
 
 /**
@@ -2651,6 +2652,15 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb);
 unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc);
 
 /**
+ * ieee80211_get_mesh_hdrlen - get mesh extension header length
+ * @meshhdr: the mesh extension header, only the flags field
+ *     (first byte) will be accessed
+ * Returns the length of the extension header, which is always at
+ * least 6 bytes and at most 18 if address 5 and 6 are present.
+ */
+unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
+
+/**
  * DOC: Data path helpers
  *
  * In addition to generic utilities, cfg80211 also offers
index 6feeccd..4af45e3 100644 (file)
@@ -525,6 +525,7 @@ static inline __u32 cookie_v6_init_sequence(struct sock *sk,
 extern void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss,
                                      int nonagle);
 extern bool tcp_may_send_now(struct sock *sk);
+extern int __tcp_retransmit_skb(struct sock *, struct sk_buff *);
 extern int tcp_retransmit_skb(struct sock *, struct sk_buff *);
 extern void tcp_retransmit_timer(struct sock *sk);
 extern void tcp_xmit_retransmit_queue(struct sock *);
index 6f0ba01..63445ed 100644 (file)
@@ -1351,7 +1351,7 @@ struct xfrm6_tunnel {
 };
 
 extern void xfrm_init(void);
-extern void xfrm4_init(int rt_hash_size);
+extern void xfrm4_init(void);
 extern int xfrm_state_init(struct net *net);
 extern void xfrm_state_fini(struct net *net);
 extern void xfrm4_state_init(void);
index 88fae8d..55367b0 100644 (file)
@@ -135,6 +135,8 @@ struct scsi_device {
                                     * because we did a bus reset. */
        unsigned use_10_for_rw:1; /* first try 10-byte read / write */
        unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */
+       unsigned no_report_opcodes:1;   /* no REPORT SUPPORTED OPERATION CODES */
+       unsigned no_write_same:1;       /* no WRITE SAME command */
        unsigned skip_ms_page_8:1;      /* do not use MODE SENSE page 0x08 */
        unsigned skip_ms_page_3f:1;     /* do not use MODE SENSE page 0x3f */
        unsigned skip_vpd_pages:1;      /* do not read VPD pages */
@@ -362,6 +364,8 @@ extern int scsi_test_unit_ready(struct scsi_device *sdev, int timeout,
                                int retries, struct scsi_sense_hdr *sshdr);
 extern int scsi_get_vpd_page(struct scsi_device *, u8 page, unsigned char *buf,
                             int buf_len);
+extern int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
+                             unsigned int len, unsigned char opcode);
 extern int scsi_device_set_state(struct scsi_device *sdev,
                                 enum scsi_device_state state);
 extern struct scsi_event *sdev_evt_alloc(enum scsi_device_event evt_type,
index bc05668..93896ad 100644 (file)
@@ -132,6 +132,7 @@ struct snd_card {
        int shutdown;                   /* this card is going down */
        int free_on_last_close;         /* free in context of file_release */
        wait_queue_head_t shutdown_sleep;
+       atomic_t refcount;              /* refcount for disconnection */
        struct device *dev;             /* device assigned to this card */
        struct device *card_dev;        /* cardX object for sysfs */
 
@@ -189,6 +190,7 @@ struct snd_minor {
        const struct file_operations *f_ops;    /* file operations */
        void *private_data;             /* private data for f_ops->open */
        struct device *dev;             /* device for sysfs */
+       struct snd_card *card_ptr;      /* assigned card instance */
 };
 
 /* return a device pointer linked to each sound device as a parent */
@@ -295,6 +297,7 @@ int snd_card_info_done(void);
 int snd_component_add(struct snd_card *card, const char *component);
 int snd_card_file_add(struct snd_card *card, struct file *file);
 int snd_card_file_remove(struct snd_card *card, struct file *file);
+void snd_card_unref(struct snd_card *card);
 
 #define snd_card_set_dev(card, devptr) ((card)->dev = (devptr))
 
index 9391706..d6fd8e5 100644 (file)
@@ -36,6 +36,7 @@
        {(unsigned long)__GFP_RECLAIMABLE,      "GFP_RECLAIMABLE"},     \
        {(unsigned long)__GFP_MOVABLE,          "GFP_MOVABLE"},         \
        {(unsigned long)__GFP_NOTRACK,          "GFP_NOTRACK"},         \
+       {(unsigned long)__GFP_NO_KSWAPD,        "GFP_NO_KSWAPD"},       \
        {(unsigned long)__GFP_OTHER_NODE,       "GFP_OTHER_NODE"}       \
        ) : "GFP_NOWAIT"
 
index 15ba03b..d06b6da 100644 (file)
@@ -377,6 +377,14 @@ DECLARE_EVENT_CLASS(xen_mmu_pgd,
 DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_pin);
 DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_unpin);
 
+TRACE_EVENT(xen_mmu_flush_tlb_all,
+           TP_PROTO(int x),
+           TP_ARGS(x),
+           TP_STRUCT__entry(__array(char, x, 0)),
+           TP_fast_assign((void)x),
+           TP_printk("%s", "")
+       );
+
 TRACE_EVENT(xen_mmu_flush_tlb,
            TP_PROTO(int x),
            TP_ARGS(x),
index e69de29..486f0af 100644 (file)
@@ -0,0 +1,4 @@
+/*
+ * There isn't anything here, but the file must not be empty or patch
+ * will delete it.
+ */
index e194387..19e765f 100644 (file)
@@ -415,3 +415,4 @@ header-y += wireless.h
 header-y += x25.h
 header-y += xattr.h
 header-y += xfrm.h
+header-y += hw_breakpoint.h
index aafaa5a..d40942c 100644 (file)
@@ -1 +1,9 @@
 # UAPI Header export list
+header-y += audio.h
+header-y += ca.h
+header-y += dmx.h
+header-y += frontend.h
+header-y += net.h
+header-y += osd.h
+header-y += version.h
+header-y += video.h
diff --git a/include/uapi/linux/dvb/dmx.h b/include/uapi/linux/dvb/dmx.h
new file mode 100644 (file)
index 0000000..b2a9ad8
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * dmx.h
+ *
+ * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
+ *                  & Ralph  Metzler <ralph@convergence.de>
+ *                    for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser 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_DVBDMX_H_
+#define _UAPI_DVBDMX_H_
+
+#include <linux/types.h>
+#ifndef __KERNEL__
+#include <time.h>
+#endif
+
+
+#define DMX_FILTER_SIZE 16
+
+typedef enum
+{
+       DMX_OUT_DECODER, /* Streaming directly to decoder. */
+       DMX_OUT_TAP,     /* Output going to a memory buffer */
+                        /* (to be retrieved via the read command).*/
+       DMX_OUT_TS_TAP,  /* Output multiplexed into a new TS  */
+                        /* (to be retrieved by reading from the */
+                        /* logical DVR device).                 */
+       DMX_OUT_TSDEMUX_TAP /* Like TS_TAP but retrieved from the DMX device */
+} dmx_output_t;
+
+
+typedef enum
+{
+       DMX_IN_FRONTEND, /* Input from a front-end device.  */
+       DMX_IN_DVR       /* Input from the logical DVR device.  */
+} dmx_input_t;
+
+
+typedef enum
+{
+       DMX_PES_AUDIO0,
+       DMX_PES_VIDEO0,
+       DMX_PES_TELETEXT0,
+       DMX_PES_SUBTITLE0,
+       DMX_PES_PCR0,
+
+       DMX_PES_AUDIO1,
+       DMX_PES_VIDEO1,
+       DMX_PES_TELETEXT1,
+       DMX_PES_SUBTITLE1,
+       DMX_PES_PCR1,
+
+       DMX_PES_AUDIO2,
+       DMX_PES_VIDEO2,
+       DMX_PES_TELETEXT2,
+       DMX_PES_SUBTITLE2,
+       DMX_PES_PCR2,
+
+       DMX_PES_AUDIO3,
+       DMX_PES_VIDEO3,
+       DMX_PES_TELETEXT3,
+       DMX_PES_SUBTITLE3,
+       DMX_PES_PCR3,
+
+       DMX_PES_OTHER
+} dmx_pes_type_t;
+
+#define DMX_PES_AUDIO    DMX_PES_AUDIO0
+#define DMX_PES_VIDEO    DMX_PES_VIDEO0
+#define DMX_PES_TELETEXT DMX_PES_TELETEXT0
+#define DMX_PES_SUBTITLE DMX_PES_SUBTITLE0
+#define DMX_PES_PCR      DMX_PES_PCR0
+
+
+typedef struct dmx_filter
+{
+       __u8  filter[DMX_FILTER_SIZE];
+       __u8  mask[DMX_FILTER_SIZE];
+       __u8  mode[DMX_FILTER_SIZE];
+} dmx_filter_t;
+
+
+struct dmx_sct_filter_params
+{
+       __u16          pid;
+       dmx_filter_t   filter;
+       __u32          timeout;
+       __u32          flags;
+#define DMX_CHECK_CRC       1
+#define DMX_ONESHOT         2
+#define DMX_IMMEDIATE_START 4
+#define DMX_KERNEL_CLIENT   0x8000
+};
+
+
+struct dmx_pes_filter_params
+{
+       __u16          pid;
+       dmx_input_t    input;
+       dmx_output_t   output;
+       dmx_pes_type_t pes_type;
+       __u32          flags;
+};
+
+typedef struct dmx_caps {
+       __u32 caps;
+       int num_decoders;
+} dmx_caps_t;
+
+typedef enum {
+       DMX_SOURCE_FRONT0 = 0,
+       DMX_SOURCE_FRONT1,
+       DMX_SOURCE_FRONT2,
+       DMX_SOURCE_FRONT3,
+       DMX_SOURCE_DVR0   = 16,
+       DMX_SOURCE_DVR1,
+       DMX_SOURCE_DVR2,
+       DMX_SOURCE_DVR3
+} dmx_source_t;
+
+struct dmx_stc {
+       unsigned int num;       /* input : which STC? 0..N */
+       unsigned int base;      /* output: divisor for stc to get 90 kHz clock */
+       __u64 stc;              /* output: stc in 'base'*90 kHz units */
+};
+
+
+#define DMX_START                _IO('o', 41)
+#define DMX_STOP                 _IO('o', 42)
+#define DMX_SET_FILTER           _IOW('o', 43, struct dmx_sct_filter_params)
+#define DMX_SET_PES_FILTER       _IOW('o', 44, struct dmx_pes_filter_params)
+#define DMX_SET_BUFFER_SIZE      _IO('o', 45)
+#define DMX_GET_PES_PIDS         _IOR('o', 47, __u16[5])
+#define DMX_GET_CAPS             _IOR('o', 48, dmx_caps_t)
+#define DMX_SET_SOURCE           _IOW('o', 49, dmx_source_t)
+#define DMX_GET_STC              _IOWR('o', 50, struct dmx_stc)
+#define DMX_ADD_PID              _IOW('o', 51, __u16)
+#define DMX_REMOVE_PID           _IOW('o', 52, __u16)
+
+#endif /* _UAPI_DVBDMX_H_ */
diff --git a/include/uapi/linux/dvb/video.h b/include/uapi/linux/dvb/video.h
new file mode 100644 (file)
index 0000000..d3d14a5
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * video.h
+ *
+ * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
+ *                  & Ralph  Metzler <ralph@convergence.de>
+ *                    for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser 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_DVBVIDEO_H_
+#define _UAPI_DVBVIDEO_H_
+
+#include <linux/types.h>
+#ifndef __KERNEL__
+#include <stdint.h>
+#include <time.h>
+#endif
+
+typedef enum {
+       VIDEO_FORMAT_4_3,     /* Select 4:3 format */
+       VIDEO_FORMAT_16_9,    /* Select 16:9 format. */
+       VIDEO_FORMAT_221_1    /* 2.21:1 */
+} video_format_t;
+
+
+typedef enum {
+        VIDEO_SYSTEM_PAL,
+        VIDEO_SYSTEM_NTSC,
+        VIDEO_SYSTEM_PALN,
+        VIDEO_SYSTEM_PALNc,
+        VIDEO_SYSTEM_PALM,
+        VIDEO_SYSTEM_NTSC60,
+        VIDEO_SYSTEM_PAL60,
+        VIDEO_SYSTEM_PALM60
+} video_system_t;
+
+
+typedef enum {
+       VIDEO_PAN_SCAN,       /* use pan and scan format */
+       VIDEO_LETTER_BOX,     /* use letterbox format */
+       VIDEO_CENTER_CUT_OUT  /* use center cut out format */
+} video_displayformat_t;
+
+typedef struct {
+       int w;
+       int h;
+       video_format_t aspect_ratio;
+} video_size_t;
+
+typedef enum {
+       VIDEO_SOURCE_DEMUX, /* Select the demux as the main source */
+       VIDEO_SOURCE_MEMORY /* If this source is selected, the stream
+                              comes from the user through the write
+                              system call */
+} video_stream_source_t;
+
+
+typedef enum {
+       VIDEO_STOPPED, /* Video is stopped */
+       VIDEO_PLAYING, /* Video is currently playing */
+       VIDEO_FREEZED  /* Video is freezed */
+} video_play_state_t;
+
+
+/* Decoder commands */
+#define VIDEO_CMD_PLAY        (0)
+#define VIDEO_CMD_STOP        (1)
+#define VIDEO_CMD_FREEZE      (2)
+#define VIDEO_CMD_CONTINUE    (3)
+
+/* Flags for VIDEO_CMD_FREEZE */
+#define VIDEO_CMD_FREEZE_TO_BLACK      (1 << 0)
+
+/* Flags for VIDEO_CMD_STOP */
+#define VIDEO_CMD_STOP_TO_BLACK        (1 << 0)
+#define VIDEO_CMD_STOP_IMMEDIATELY             (1 << 1)
+
+/* Play input formats: */
+/* The decoder has no special format requirements */
+#define VIDEO_PLAY_FMT_NONE         (0)
+/* The decoder requires full GOPs */
+#define VIDEO_PLAY_FMT_GOP          (1)
+
+/* The structure must be zeroed before use by the application
+   This ensures it can be extended safely in the future. */
+struct video_command {
+       __u32 cmd;
+       __u32 flags;
+       union {
+               struct {
+                       __u64 pts;
+               } stop;
+
+               struct {
+                       /* 0 or 1000 specifies normal speed,
+                          1 specifies forward single stepping,
+                          -1 specifies backward single stepping,
+                          >1: playback at speed/1000 of the normal speed,
+                          <-1: reverse playback at (-speed/1000) of the normal speed. */
+                       __s32 speed;
+                       __u32 format;
+               } play;
+
+               struct {
+                       __u32 data[16];
+               } raw;
+       };
+};
+
+/* FIELD_UNKNOWN can be used if the hardware does not know whether
+   the Vsync is for an odd, even or progressive (i.e. non-interlaced)
+   field. */
+#define VIDEO_VSYNC_FIELD_UNKNOWN      (0)
+#define VIDEO_VSYNC_FIELD_ODD          (1)
+#define VIDEO_VSYNC_FIELD_EVEN         (2)
+#define VIDEO_VSYNC_FIELD_PROGRESSIVE  (3)
+
+struct video_event {
+       __s32 type;
+#define VIDEO_EVENT_SIZE_CHANGED       1
+#define VIDEO_EVENT_FRAME_RATE_CHANGED 2
+#define VIDEO_EVENT_DECODER_STOPPED    3
+#define VIDEO_EVENT_VSYNC              4
+       __kernel_time_t timestamp;
+       union {
+               video_size_t size;
+               unsigned int frame_rate;        /* in frames per 1000sec */
+               unsigned char vsync_field;      /* unknown/odd/even/progressive */
+       } u;
+};
+
+
+struct video_status {
+       int                   video_blank;   /* blank video on freeze? */
+       video_play_state_t    play_state;    /* current state of playback */
+       video_stream_source_t stream_source; /* current source (demux/memory) */
+       video_format_t        video_format;  /* current aspect ratio of stream*/
+       video_displayformat_t display_format;/* selected cropping mode */
+};
+
+
+struct video_still_picture {
+       char __user *iFrame;        /* pointer to a single iframe in memory */
+       __s32 size;
+};
+
+
+typedef
+struct video_highlight {
+       int     active;      /*    1=show highlight, 0=hide highlight */
+       __u8    contrast1;   /*    7- 4  Pattern pixel contrast */
+                            /*    3- 0  Background pixel contrast */
+       __u8    contrast2;   /*    7- 4  Emphasis pixel-2 contrast */
+                            /*    3- 0  Emphasis pixel-1 contrast */
+       __u8    color1;      /*    7- 4  Pattern pixel color */
+                            /*    3- 0  Background pixel color */
+       __u8    color2;      /*    7- 4  Emphasis pixel-2 color */
+                            /*    3- 0  Emphasis pixel-1 color */
+       __u32    ypos;       /*   23-22  auto action mode */
+                            /*   21-12  start y */
+                            /*    9- 0  end y */
+       __u32    xpos;       /*   23-22  button color number */
+                            /*   21-12  start x */
+                            /*    9- 0  end x */
+} video_highlight_t;
+
+
+typedef struct video_spu {
+       int active;
+       int stream_id;
+} video_spu_t;
+
+
+typedef struct video_spu_palette {      /* SPU Palette information */
+       int length;
+       __u8 __user *palette;
+} video_spu_palette_t;
+
+
+typedef struct video_navi_pack {
+       int length;          /* 0 ... 1024 */
+       __u8 data[1024];
+} video_navi_pack_t;
+
+
+typedef __u16 video_attributes_t;
+/*   bits: descr. */
+/*   15-14 Video compression mode (0=MPEG-1, 1=MPEG-2) */
+/*   13-12 TV system (0=525/60, 1=625/50) */
+/*   11-10 Aspect ratio (0=4:3, 3=16:9) */
+/*    9- 8 permitted display mode on 4:3 monitor (0=both, 1=only pan-sca */
+/*    7    line 21-1 data present in GOP (1=yes, 0=no) */
+/*    6    line 21-2 data present in GOP (1=yes, 0=no) */
+/*    5- 3 source resolution (0=720x480/576, 1=704x480/576, 2=352x480/57 */
+/*    2    source letterboxed (1=yes, 0=no) */
+/*    0    film/camera mode (0=camera, 1=film (625/50 only)) */
+
+
+/* bit definitions for capabilities: */
+/* can the hardware decode MPEG1 and/or MPEG2? */
+#define VIDEO_CAP_MPEG1   1
+#define VIDEO_CAP_MPEG2   2
+/* can you send a system and/or program stream to video device?
+   (you still have to open the video and the audio device but only
+    send the stream to the video device) */
+#define VIDEO_CAP_SYS     4
+#define VIDEO_CAP_PROG    8
+/* can the driver also handle SPU, NAVI and CSS encoded data?
+   (CSS API is not present yet) */
+#define VIDEO_CAP_SPU    16
+#define VIDEO_CAP_NAVI   32
+#define VIDEO_CAP_CSS    64
+
+
+#define VIDEO_STOP                 _IO('o', 21)
+#define VIDEO_PLAY                 _IO('o', 22)
+#define VIDEO_FREEZE               _IO('o', 23)
+#define VIDEO_CONTINUE             _IO('o', 24)
+#define VIDEO_SELECT_SOURCE        _IO('o', 25)
+#define VIDEO_SET_BLANK            _IO('o', 26)
+#define VIDEO_GET_STATUS           _IOR('o', 27, struct video_status)
+#define VIDEO_GET_EVENT            _IOR('o', 28, struct video_event)
+#define VIDEO_SET_DISPLAY_FORMAT   _IO('o', 29)
+#define VIDEO_STILLPICTURE         _IOW('o', 30, struct video_still_picture)
+#define VIDEO_FAST_FORWARD         _IO('o', 31)
+#define VIDEO_SLOWMOTION           _IO('o', 32)
+#define VIDEO_GET_CAPABILITIES     _IOR('o', 33, unsigned int)
+#define VIDEO_CLEAR_BUFFER         _IO('o',  34)
+#define VIDEO_SET_ID               _IO('o', 35)
+#define VIDEO_SET_STREAMTYPE       _IO('o', 36)
+#define VIDEO_SET_FORMAT           _IO('o', 37)
+#define VIDEO_SET_SYSTEM           _IO('o', 38)
+#define VIDEO_SET_HIGHLIGHT        _IOW('o', 39, video_highlight_t)
+#define VIDEO_SET_SPU              _IOW('o', 50, video_spu_t)
+#define VIDEO_SET_SPU_PALETTE      _IOW('o', 51, video_spu_palette_t)
+#define VIDEO_GET_NAVI             _IOR('o', 52, video_navi_pack_t)
+#define VIDEO_SET_ATTRIBUTES       _IO('o', 53)
+#define VIDEO_GET_SIZE             _IOR('o', 55, video_size_t)
+#define VIDEO_GET_FRAME_RATE       _IOR('o', 56, unsigned int)
+
+/**
+ * VIDEO_GET_PTS
+ *
+ * Read the 33 bit presentation time stamp as defined
+ * in ITU T-REC-H.222.0 / ISO/IEC 13818-1.
+ *
+ * The PTS should belong to the currently played
+ * frame if possible, but may also be a value close to it
+ * like the PTS of the last decoded frame or the last PTS
+ * extracted by the PES parser.
+ */
+#define VIDEO_GET_PTS              _IOR('o', 57, __u64)
+
+/* Read the number of displayed frames since the decoder was started */
+#define VIDEO_GET_FRAME_COUNT             _IOR('o', 58, __u64)
+
+#define VIDEO_COMMAND             _IOWR('o', 59, struct video_command)
+#define VIDEO_TRY_COMMAND         _IOWR('o', 60, struct video_command)
+
+#endif /* _UAPI_DVBVIDEO_H_ */
index 1065078..3921e33 100644 (file)
@@ -9,8 +9,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#ifndef _LINUX_ELF_FDPIC_H
-#define _LINUX_ELF_FDPIC_H
+#ifndef _UAPI_LINUX_ELF_FDPIC_H
+#define _UAPI_LINUX_ELF_FDPIC_H
 
 #include <linux/elf.h>
 
@@ -31,40 +31,4 @@ struct elf32_fdpic_loadmap {
 
 #define ELF32_FDPIC_LOADMAP_VERSION    0x0000
 
-#ifndef __KERNEL__
-/*
- * binfmt binary parameters structure
- */
-struct elf_fdpic_params {
-       struct elfhdr                   hdr;            /* ref copy of ELF header */
-       struct elf_phdr                 *phdrs;         /* ref copy of PT_PHDR table */
-       struct elf32_fdpic_loadmap      *loadmap;       /* loadmap to be passed to userspace */
-       unsigned long                   elfhdr_addr;    /* mapped ELF header user address */
-       unsigned long                   ph_addr;        /* mapped PT_PHDR user address */
-       unsigned long                   map_addr;       /* mapped loadmap user address */
-       unsigned long                   entry_addr;     /* mapped entry user address */
-       unsigned long                   stack_size;     /* stack size requested (PT_GNU_STACK) */
-       unsigned long                   dynamic_addr;   /* mapped PT_DYNAMIC user address */
-       unsigned long                   load_addr;      /* user address at which to map binary */
-       unsigned long                   flags;
-#define ELF_FDPIC_FLAG_ARRANGEMENT     0x0000000f      /* PT_LOAD arrangement flags */
-#define ELF_FDPIC_FLAG_INDEPENDENT     0x00000000      /* PT_LOADs can be put anywhere */
-#define ELF_FDPIC_FLAG_HONOURVADDR     0x00000001      /* PT_LOAD.vaddr must be honoured */
-#define ELF_FDPIC_FLAG_CONSTDISP       0x00000002      /* PT_LOADs require constant
-                                                        * displacement */
-#define ELF_FDPIC_FLAG_CONTIGUOUS      0x00000003      /* PT_LOADs should be contiguous */
-#define ELF_FDPIC_FLAG_EXEC_STACK      0x00000010      /* T if stack to be executable */
-#define ELF_FDPIC_FLAG_NOEXEC_STACK    0x00000020      /* T if stack not to be executable */
-#define ELF_FDPIC_FLAG_EXECUTABLE      0x00000040      /* T if this object is the executable */
-#define ELF_FDPIC_FLAG_PRESENT         0x80000000      /* T if this object is present */
-};
-
-#ifdef CONFIG_MMU
-extern void elf_fdpic_arch_lay_out_mm(struct elf_fdpic_params *exec_params,
-                                     struct elf_fdpic_params *interp_params,
-                                     unsigned long *start_stack,
-                                     unsigned long *start_brk);
-#endif
-#endif /* __KERNEL__ */
-
-#endif /* _LINUX_ELF_FDPIC_H */
+#endif /* _UAPI_LINUX_ELF_FDPIC_H */
index 8c99ce7..2c267bc 100644 (file)
@@ -25,7 +25,6 @@
 #define EPOLL_CTL_ADD 1
 #define EPOLL_CTL_DEL 2
 #define EPOLL_CTL_MOD 3
-#define EPOLL_CTL_DISABLE 4
 
 /*
  * Request the handling of system wakeup events so as to prevent system suspends
index 9fcc880..780d4c6 100644 (file)
@@ -57,85 +57,6 @@ struct inodes_stat_t {
 
 #define NR_FILE  8192  /* this can well be larger on a larger system */
 
-#define MAY_EXEC               0x00000001
-#define MAY_WRITE              0x00000002
-#define MAY_READ               0x00000004
-#define MAY_APPEND             0x00000008
-#define MAY_ACCESS             0x00000010
-#define MAY_OPEN               0x00000020
-#define MAY_CHDIR              0x00000040
-/* called from RCU mode, don't block */
-#define MAY_NOT_BLOCK          0x00000080
-
-/*
- * flags in file.f_mode.  Note that FMODE_READ and FMODE_WRITE must correspond
- * to O_WRONLY and O_RDWR via the strange trick in __dentry_open()
- */
-
-/* file is open for reading */
-#define FMODE_READ             ((__force fmode_t)0x1)
-/* file is open for writing */
-#define FMODE_WRITE            ((__force fmode_t)0x2)
-/* file is seekable */
-#define FMODE_LSEEK            ((__force fmode_t)0x4)
-/* file can be accessed using pread */
-#define FMODE_PREAD            ((__force fmode_t)0x8)
-/* file can be accessed using pwrite */
-#define FMODE_PWRITE           ((__force fmode_t)0x10)
-/* File is opened for execution with sys_execve / sys_uselib */
-#define FMODE_EXEC             ((__force fmode_t)0x20)
-/* File is opened with O_NDELAY (only set for block devices) */
-#define FMODE_NDELAY           ((__force fmode_t)0x40)
-/* File is opened with O_EXCL (only set for block devices) */
-#define FMODE_EXCL             ((__force fmode_t)0x80)
-/* File is opened using open(.., 3, ..) and is writeable only for ioctls
-   (specialy hack for floppy.c) */
-#define FMODE_WRITE_IOCTL      ((__force fmode_t)0x100)
-/* 32bit hashes as llseek() offset (for directories) */
-#define FMODE_32BITHASH         ((__force fmode_t)0x200)
-/* 64bit hashes as llseek() offset (for directories) */
-#define FMODE_64BITHASH         ((__force fmode_t)0x400)
-
-/*
- * Don't update ctime and mtime.
- *
- * Currently a special hack for the XFS open_by_handle ioctl, but we'll
- * hopefully graduate it to a proper O_CMTIME flag supported by open(2) soon.
- */
-#define FMODE_NOCMTIME         ((__force fmode_t)0x800)
-
-/* Expect random access pattern */
-#define FMODE_RANDOM           ((__force fmode_t)0x1000)
-
-/* File is huge (eg. /dev/kmem): treat loff_t as unsigned */
-#define FMODE_UNSIGNED_OFFSET  ((__force fmode_t)0x2000)
-
-/* File is opened with O_PATH; almost nothing can be done with it */
-#define FMODE_PATH             ((__force fmode_t)0x4000)
-
-/* File was opened by fanotify and shouldn't generate fanotify events */
-#define FMODE_NONOTIFY         ((__force fmode_t)0x1000000)
-
-/*
- * Flag for rw_copy_check_uvector and compat_rw_copy_check_uvector
- * that indicates that they should check the contents of the iovec are
- * valid, but not check the memory that the iovec elements
- * points too.
- */
-#define CHECK_IOVEC_ONLY -1
-
-#define SEL_IN         1
-#define SEL_OUT                2
-#define SEL_EX         4
-
-/* public flags for file_system_type */
-#define FS_REQUIRES_DEV 1 
-#define FS_BINARY_MOUNTDATA 2
-#define FS_HAS_SUBTYPE 4
-#define FS_REVAL_DOT   16384   /* Check the paths ".", ".." for staleness */
-#define FS_RENAME_DOES_D_MOVE  32768   /* FS will handle d_move()
-                                        * during rename() internally.
-                                        */
 
 /*
  * These are the fs-independent mount-flags: up to 32 flags are supported
@@ -181,59 +102,6 @@ struct inodes_stat_t {
 #define MS_MGC_VAL 0xC0ED0000
 #define MS_MGC_MSK 0xffff0000
 
-/* Inode flags - they have nothing to superblock flags now */
-
-#define S_SYNC         1       /* Writes are synced at once */
-#define S_NOATIME      2       /* Do not update access times */
-#define S_APPEND       4       /* Append-only file */
-#define S_IMMUTABLE    8       /* Immutable file */
-#define S_DEAD         16      /* removed, but still open directory */
-#define S_NOQUOTA      32      /* Inode is not counted to quota */
-#define S_DIRSYNC      64      /* Directory modifications are synchronous */
-#define S_NOCMTIME     128     /* Do not update file c/mtime */
-#define S_SWAPFILE     256     /* Do not truncate: swapon got its bmaps */
-#define S_PRIVATE      512     /* Inode is fs-internal */
-#define S_IMA          1024    /* Inode has an associated IMA struct */
-#define S_AUTOMOUNT    2048    /* Automount/referral quasi-directory */
-#define S_NOSEC                4096    /* no suid or xattr security attributes */
-
-/*
- * Note that nosuid etc flags are inode-specific: setting some file-system
- * flags just means all the inodes inherit those flags by default. It might be
- * possible to override it selectively if you really wanted to with some
- * ioctl() that is not currently implemented.
- *
- * Exception: MS_RDONLY is always applied to the entire file system.
- *
- * Unfortunately, it is possible to change a filesystems flags with it mounted
- * with files in use.  This means that all of the inodes will not have their
- * i_flags updated.  Hence, i_flags no longer inherit the superblock mount
- * flags, so these have to be checked separately. -- rmk@arm.uk.linux.org
- */
-#define __IS_FLG(inode,flg) ((inode)->i_sb->s_flags & (flg))
-
-#define IS_RDONLY(inode) ((inode)->i_sb->s_flags & MS_RDONLY)
-#define IS_SYNC(inode)         (__IS_FLG(inode, MS_SYNCHRONOUS) || \
-                                       ((inode)->i_flags & S_SYNC))
-#define IS_DIRSYNC(inode)      (__IS_FLG(inode, MS_SYNCHRONOUS|MS_DIRSYNC) || \
-                                       ((inode)->i_flags & (S_SYNC|S_DIRSYNC)))
-#define IS_MANDLOCK(inode)     __IS_FLG(inode, MS_MANDLOCK)
-#define IS_NOATIME(inode)   __IS_FLG(inode, MS_RDONLY|MS_NOATIME)
-#define IS_I_VERSION(inode)   __IS_FLG(inode, MS_I_VERSION)
-
-#define IS_NOQUOTA(inode)      ((inode)->i_flags & S_NOQUOTA)
-#define IS_APPEND(inode)       ((inode)->i_flags & S_APPEND)
-#define IS_IMMUTABLE(inode)    ((inode)->i_flags & S_IMMUTABLE)
-#define IS_POSIXACL(inode)     __IS_FLG(inode, MS_POSIXACL)
-
-#define IS_DEADDIR(inode)      ((inode)->i_flags & S_DEAD)
-#define IS_NOCMTIME(inode)     ((inode)->i_flags & S_NOCMTIME)
-#define IS_SWAPFILE(inode)     ((inode)->i_flags & S_SWAPFILE)
-#define IS_PRIVATE(inode)      ((inode)->i_flags & S_PRIVATE)
-#define IS_IMA(inode)          ((inode)->i_flags & S_IMA)
-#define IS_AUTOMOUNT(inode)    ((inode)->i_flags & S_AUTOMOUNT)
-#define IS_NOSEC(inode)                ((inode)->i_flags & S_NOSEC)
-
 /* the read-only stuff doesn't really belong here, but any other place is
    probably as bad and I don't want to create yet another include file. */
 
index aafaa5a..30ab3cd 100644 (file)
@@ -1 +1,2 @@
 # UAPI Header export list
+header-y += hsi_char.h
diff --git a/include/uapi/linux/hw_breakpoint.h b/include/uapi/linux/hw_breakpoint.h
new file mode 100644 (file)
index 0000000..b04000a
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef _UAPI_LINUX_HW_BREAKPOINT_H
+#define _UAPI_LINUX_HW_BREAKPOINT_H
+
+enum {
+       HW_BREAKPOINT_LEN_1 = 1,
+       HW_BREAKPOINT_LEN_2 = 2,
+       HW_BREAKPOINT_LEN_4 = 4,
+       HW_BREAKPOINT_LEN_8 = 8,
+};
+
+enum {
+       HW_BREAKPOINT_EMPTY     = 0,
+       HW_BREAKPOINT_R         = 1,
+       HW_BREAKPOINT_W         = 2,
+       HW_BREAKPOINT_RW        = HW_BREAKPOINT_R | HW_BREAKPOINT_W,
+       HW_BREAKPOINT_X         = 4,
+       HW_BREAKPOINT_INVALID   = HW_BREAKPOINT_RW | HW_BREAKPOINT_X,
+};
+
+enum bp_type_idx {
+       TYPE_INST       = 0,
+#ifdef CONFIG_HAVE_MIXED_BREAKPOINTS_REGS
+       TYPE_DATA       = 0,
+#else
+       TYPE_DATA       = 1,
+#endif
+       TYPE_MAX
+};
+
+#endif /* _UAPI_LINUX_HW_BREAKPOINT_H */
index e69de29..ae5704f 100644 (file)
@@ -0,0 +1,4 @@
+/*
+ * There isn't anything here anymore, but the file must not be empty or patch
+ * will delete it.
+ */
index a49c4af..b29272d 100644 (file)
@@ -8,4 +8,13 @@
 #define OOM_SCORE_ADJ_MIN      (-1000)
 #define OOM_SCORE_ADJ_MAX      1000
 
+/*
+ * /proc/<pid>/oom_adj set to -17 protects from the oom killer for legacy
+ * purposes.
+ */
+#define OOM_DISABLE (-17)
+/* inclusive */
+#define OOM_ADJUST_MIN (-16)
+#define OOM_ADJUST_MAX 15
+
 #endif /* _UAPI__INCLUDE_LINUX_OOM_H */
index aafaa5a..e2c3d25 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 c4b89a5..e962faa 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 aafaa5a..6cb4ea8 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 */
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__ */
diff --git a/include/xen/Kbuild b/include/xen/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index aecee9d..694dcaf 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,
index b193fa2..13e43e4 100644 (file)
@@ -5,6 +5,36 @@
 #include <xen/interface/hvm/params.h>
 #include <asm/xen/hypercall.h>
 
+static const char *param_name(int op)
+{
+#define PARAM(x) [HVM_PARAM_##x] = #x
+       static const char *const names[] = {
+               PARAM(CALLBACK_IRQ),
+               PARAM(STORE_PFN),
+               PARAM(STORE_EVTCHN),
+               PARAM(PAE_ENABLED),
+               PARAM(IOREQ_PFN),
+               PARAM(BUFIOREQ_PFN),
+               PARAM(TIMER_MODE),
+               PARAM(HPET_ENABLED),
+               PARAM(IDENT_PT),
+               PARAM(DM_DOMAIN),
+               PARAM(ACPI_S_STATE),
+               PARAM(VM86_TSS),
+               PARAM(VPT_ALIGN),
+               PARAM(CONSOLE_PFN),
+               PARAM(CONSOLE_EVTCHN),
+       };
+#undef PARAM
+
+       if (op >= ARRAY_SIZE(names))
+               return "unknown";
+
+       if (!names[op])
+               return "reserved";
+
+       return names[op];
+}
 static inline int hvm_get_parameter(int idx, uint64_t *value)
 {
        struct xen_hvm_param xhv;
@@ -14,8 +44,8 @@ static inline int hvm_get_parameter(int idx, uint64_t *value)
        xhv.index = idx;
        r = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv);
        if (r < 0) {
-               printk(KERN_ERR "Cannot get hvm parameter %d: %d!\n",
-                       idx, r);
+               printk(KERN_ERR "Cannot get hvm parameter %s (%d): %d!\n",
+                       param_name(idx), idx, r);
                return r;
        }
        *value = xhv.value;
index f9f8b97..e40fae9 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 b66d04c..90712e2 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 9cf77ab..e33e09d 100644 (file)
@@ -442,9 +442,11 @@ void __init __weak smp_setup_processor_id(void)
 {
 }
 
+# if THREAD_SIZE >= PAGE_SIZE
 void __init __weak thread_info_cache_init(void)
 {
 }
+#endif
 
 /*
  * Set up kernel memory allocators
index 0dfeca4..86e3285 100644 (file)
@@ -174,10 +174,8 @@ signing_key.priv signing_key.x509: x509.genkey
        @echo "###"
        @echo "### If this takes a long time, you might wish to run rngd in the"
        @echo "### background to keep the supply of entropy topped up.  It"
-       @echo "### needs to be run as root, and should use a hardware random"
-       @echo "### number generator if one is available, eg:"
-       @echo "###"
-       @echo "###     rngd -r /dev/hwrandom"
+       @echo "### needs to be run as root, and uses a hardware random"
+       @echo "### number generator if one is available."
        @echo "###"
        openssl req -new -nodes -utf8 $(sign_key_with_hash) -days 36500 -batch \
                -x509 -config x509.genkey \
index 13774b3..f24f724 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,31 +4814,20 @@ 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);
 }
 
@@ -4895,19 +4883,10 @@ 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)) {
-                       /*
-                        * 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.
-                        */
+               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);
        }
 }
index 42bd331..f45657f 100644 (file)
@@ -348,11 +348,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 9a7b487..fe8a916 100644 (file)
@@ -111,14 +111,16 @@ static unsigned int max_task_bp_pinned(int cpu, enum bp_type_idx type)
  * Count the number of breakpoints of the same type and same task.
  * The given event must be not on the list.
  */
-static int task_bp_pinned(struct perf_event *bp, enum bp_type_idx type)
+static int task_bp_pinned(int cpu, struct perf_event *bp, enum bp_type_idx type)
 {
        struct task_struct *tsk = bp->hw.bp_target;
        struct perf_event *iter;
        int count = 0;
 
        list_for_each_entry(iter, &bp_task_head, hw.bp_list) {
-               if (iter->hw.bp_target == tsk && find_slot_idx(iter) == type)
+               if (iter->hw.bp_target == tsk &&
+                   find_slot_idx(iter) == type &&
+                   cpu == iter->cpu)
                        count += hw_breakpoint_weight(iter);
        }
 
@@ -141,7 +143,7 @@ fetch_bp_busy_slots(struct bp_busy_slots *slots, struct perf_event *bp,
                if (!tsk)
                        slots->pinned += max_task_bp_pinned(cpu, type);
                else
-                       slots->pinned += task_bp_pinned(bp, type);
+                       slots->pinned += task_bp_pinned(cpu, bp, type);
                slots->flexible = per_cpu(nr_bp_flexible[type], cpu);
 
                return;
@@ -154,7 +156,7 @@ fetch_bp_busy_slots(struct bp_busy_slots *slots, struct perf_event *bp,
                if (!tsk)
                        nr += max_task_bp_pinned(cpu, type);
                else
-                       nr += task_bp_pinned(bp, type);
+                       nr += task_bp_pinned(cpu, bp, type);
 
                if (nr > slots->pinned)
                        slots->pinned = nr;
@@ -188,7 +190,7 @@ static void toggle_bp_task_slot(struct perf_event *bp, int cpu, bool enable,
        int old_idx = 0;
        int idx = 0;
 
-       old_count = task_bp_pinned(bp, type);
+       old_count = task_bp_pinned(cpu, bp, type);
        old_idx = old_count - 1;
        idx = old_idx + weight;
 
index 98256bc..5cc4e7e 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)
@@ -264,63 +296,6 @@ put_old:
 }
 
 /**
- * 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.
  * @mm: the probed process address space.
@@ -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 3717e7b..19eb089 100644 (file)
@@ -716,7 +716,7 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb,
                                struct futex_pi_state **ps,
                                struct task_struct *task, int set_waiters)
 {
-       int lock_taken, ret, ownerdied = 0;
+       int lock_taken, ret, force_take = 0;
        u32 uval, newval, curval, vpid = task_pid_vnr(task);
 
 retry:
@@ -755,17 +755,15 @@ retry:
        newval = curval | FUTEX_WAITERS;
 
        /*
-        * There are two cases, where a futex might have no owner (the
-        * owner TID is 0): OWNER_DIED. We take over the futex in this
-        * case. We also do an unconditional take over, when the owner
-        * of the futex died.
-        *
-        * This is safe as we are protected by the hash bucket lock !
+        * Should we force take the futex? See below.
         */
-       if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) {
-               /* Keep the OWNER_DIED bit */
+       if (unlikely(force_take)) {
+               /*
+                * Keep the OWNER_DIED and the WAITERS bit and set the
+                * new TID value.
+                */
                newval = (curval & ~FUTEX_TID_MASK) | vpid;
-               ownerdied = 0;
+               force_take = 0;
                lock_taken = 1;
        }
 
@@ -775,7 +773,7 @@ retry:
                goto retry;
 
        /*
-        * We took the lock due to owner died take over.
+        * We took the lock due to forced take over.
         */
        if (unlikely(lock_taken))
                return 1;
@@ -790,20 +788,25 @@ retry:
                switch (ret) {
                case -ESRCH:
                        /*
-                        * No owner found for this futex. Check if the
-                        * OWNER_DIED bit is set to figure out whether
-                        * this is a robust futex or not.
+                        * We failed to find an owner for this
+                        * futex. So we have no pi_state to block
+                        * on. This can happen in two cases:
+                        *
+                        * 1) The owner died
+                        * 2) A stale FUTEX_WAITERS bit
+                        *
+                        * Re-read the futex value.
                         */
                        if (get_futex_value_locked(&curval, uaddr))
                                return -EFAULT;
 
                        /*
-                        * We simply start over in case of a robust
-                        * futex. The code above will take the futex
-                        * and return happy.
+                        * If the owner died or we have a stale
+                        * WAITERS bit the owner TID in the user space
+                        * futex is 0.
                         */
-                       if (curval & FUTEX_OWNER_DIED) {
-                               ownerdied = 1;
+                       if (!(curval & FUTEX_TID_MASK)) {
+                               force_take = 1;
                                goto retry;
                        }
                default:
@@ -840,6 +843,9 @@ static void wake_futex(struct futex_q *q)
 {
        struct task_struct *p = q->task;
 
+       if (WARN(q->pi_state || q->rt_waiter, "refusing to wake PI futex\n"))
+               return;
+
        /*
         * We set q->lock_ptr = NULL _before_ we wake up the task. If
         * a non-futex wake up happens on another CPU then the task
@@ -1075,6 +1081,10 @@ retry_private:
 
        plist_for_each_entry_safe(this, next, head, list) {
                if (match_futex (&this->key, &key1)) {
+                       if (this->pi_state || this->rt_waiter) {
+                               ret = -EINVAL;
+                               goto out_unlock;
+                       }
                        wake_futex(this);
                        if (++ret >= nr_wake)
                                break;
@@ -1087,6 +1097,10 @@ retry_private:
                op_ret = 0;
                plist_for_each_entry_safe(this, next, head, list) {
                        if (match_futex (&this->key, &key2)) {
+                               if (this->pi_state || this->rt_waiter) {
+                                       ret = -EINVAL;
+                                       goto out_unlock;
+                               }
                                wake_futex(this);
                                if (++op_ret >= nr_wake2)
                                        break;
@@ -1095,6 +1109,7 @@ retry_private:
                ret += op_ret;
        }
 
+out_unlock:
        double_unlock_hb(hb1, hb2);
 out_put_keys:
        put_futex_key(&key2);
@@ -1384,9 +1399,13 @@ retry_private:
                /*
                 * FUTEX_WAIT_REQEUE_PI and FUTEX_CMP_REQUEUE_PI should always
                 * be paired with each other and no other futex ops.
+                *
+                * We should never be requeueing a futex_q with a pi_state,
+                * which is awaiting a futex_unlock_pi().
                 */
                if ((requeue_pi && !this->rt_waiter) ||
-                   (!requeue_pi && this->rt_waiter)) {
+                   (!requeue_pi && this->rt_waiter) ||
+                   this->pi_state) {
                        ret = -EINVAL;
                        break;
                }
index 4e69e24..96f3a1d 100644 (file)
@@ -177,8 +177,8 @@ struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
                        irq_base = irq_alloc_descs(first_irq, first_irq, size,
                                                   of_node_to_nid(of_node));
                        if (irq_base < 0) {
-                               WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
-                                    first_irq);
+                               pr_info("Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
+                                       first_irq);
                                irq_base = first_irq;
                        }
                } else
index 4646eb2..767e559 100644 (file)
@@ -21,10 +21,10 @@ struct key *modsign_keyring;
 extern __initdata const u8 modsign_certificate_list[];
 extern __initdata const u8 modsign_certificate_list_end[];
 asm(".section .init.data,\"aw\"\n"
-    "modsign_certificate_list:\n"
+    SYMBOL_PREFIX "modsign_certificate_list:\n"
     ".incbin \"signing_key.x509\"\n"
     ".incbin \"extra_certificates\"\n"
-    "modsign_certificate_list_end:"
+    SYMBOL_PREFIX "modsign_certificate_list_end:"
     );
 
 /*
index 6114a13..24f9247 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 0e2da86..6e48c3a 100644 (file)
@@ -2293,12 +2293,17 @@ static void layout_symtab(struct module *mod, struct load_info *info)
        src = (void *)info->hdr + symsect->sh_offset;
        nsrc = symsect->sh_size / sizeof(*src);
 
+       /* strtab always starts with a nul, so offset 0 is the empty string. */
+       strtab_size = 1;
+
        /* Compute total space required for the core symbols' strtab. */
-       for (ndst = i = strtab_size = 1; i < nsrc; ++i, ++src)
-               if (is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) {
-                       strtab_size += strlen(&info->strtab[src->st_name]) + 1;
+       for (ndst = i = 0; i < nsrc; i++) {
+               if (i == 0 ||
+                   is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) {
+                       strtab_size += strlen(&info->strtab[src[i].st_name])+1;
                        ndst++;
                }
+       }
 
        /* Append room for core symbols at end of core part. */
        info->symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1);
@@ -2332,15 +2337,15 @@ static void add_kallsyms(struct module *mod, const struct load_info *info)
        mod->core_symtab = dst = mod->module_core + info->symoffs;
        mod->core_strtab = s = mod->module_core + info->stroffs;
        src = mod->symtab;
-       *dst = *src;
        *s++ = 0;
-       for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) {
-               if (!is_core_symbol(src, info->sechdrs, info->hdr->e_shnum))
-                       continue;
-
-               dst[ndst] = *src;
-               dst[ndst++].st_name = s - mod->core_strtab;
-               s += strlcpy(s, &mod->strtab[src->st_name], KSYM_NAME_LEN) + 1;
+       for (ndst = i = 0; i < mod->num_symtab; i++) {
+               if (i == 0 ||
+                   is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) {
+                       dst[ndst] = src[i];
+                       dst[ndst++].st_name = s - mod->core_strtab;
+                       s += strlcpy(s, &mod->strtab[src[i].st_name],
+                                    KSYM_NAME_LEN) + 1;
+               }
        }
        mod->core_num_syms = ndst;
 }
@@ -2421,25 +2426,17 @@ static inline void kmemleak_load_module(const struct module *mod,
 
 #ifdef CONFIG_MODULE_SIG
 static int module_sig_check(struct load_info *info,
-                           const void *mod, unsigned long *len)
+                           const void *mod, unsigned long *_len)
 {
        int err = -ENOKEY;
-       const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
-       const void *p = mod, *end = mod + *len;
-
-       /* 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++;
+       unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
+       unsigned long len = *_len;
+
+       if (len > markerlen &&
+           memcmp(mod + len - markerlen, MODULE_SIG_STRING, markerlen) == 0) {
+               /* We truncate the module to discard the signature */
+               *_len -= markerlen;
+               err = mod_verify_sig(mod, _len);
        }
 
        if (!err) {
index 6b09f69..f2970bd 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 478bad2..7b07cc0 100644 (file)
@@ -71,12 +71,22 @@ err_alloc:
        return NULL;
 }
 
+/* MAX_PID_NS_LEVEL is needed for limiting size of 'struct pid' */
+#define MAX_PID_NS_LEVEL 32
+
 static struct pid_namespace *create_pid_namespace(struct pid_namespace *parent_pid_ns)
 {
        struct pid_namespace *ns;
        unsigned int level = parent_pid_ns->level + 1;
-       int i, err = -ENOMEM;
+       int i;
+       int err;
+
+       if (level > MAX_PID_NS_LEVEL) {
+               err = -EINVAL;
+               goto out;
+       }
 
+       err = -ENOMEM;
        ns = kmem_cache_zalloc(pid_ns_cachep, GFP_KERNEL);
        if (ns == NULL)
                goto out;
@@ -133,19 +143,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);
+}
+
+void put_pid_ns(struct pid_namespace *ns)
+{
+       struct pid_namespace *parent;
 
-       if (parent != NULL)
-               put_pid_ns(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 f458238..1c16f91 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 846bd42..9322ff7 100644 (file)
@@ -213,6 +213,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 3c9d764..7c33ed2 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 66a2ea3..2d607f4 100644 (file)
@@ -1890,7 +1890,6 @@ static int __cpuinit console_cpu_notify(struct notifier_block *self,
        switch (action) {
        case CPU_ONLINE:
        case CPU_DEAD:
-       case CPU_DYING:
        case CPU_DOWN_FAILED:
        case CPU_UP_CANCELED:
                console_lock();
index 0984a21..15f60d0 100644 (file)
@@ -143,15 +143,11 @@ autogroup_move_group(struct task_struct *p, struct autogroup *ag)
 
        p->signal->autogroup = autogroup_kref_get(ag);
 
-       if (!ACCESS_ONCE(sysctl_sched_autogroup_enabled))
-               goto out;
-
        t = p;
        do {
                sched_move_task(t);
        } while_each_thread(p, t);
 
-out:
        unlock_task_sighand(p, &flags);
        autogroup_kref_put(prev);
 }
index 8bd0471..443232e 100644 (file)
@@ -4,11 +4,6 @@
 #include <linux/rwsem.h>
 
 struct autogroup {
-       /*
-        * reference doesn't mean how many thread attach to this
-        * autogroup now. It just stands for the number of task
-        * could use this autogroup.
-        */
        struct kref             kref;
        struct task_group       *tg;
        struct rw_semaphore     lock;
index c5cb5b9..e6e0ece 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 a402608..6f33706 100644 (file)
@@ -526,6 +526,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 +623,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();
 
index b32ed0e..b979426 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 9d4c8d5..c8c21be 100644 (file)
@@ -116,7 +116,7 @@ static unsigned long get_timestamp(int this_cpu)
        return cpu_clock(this_cpu) >> 30LL;  /* 2^30 ~= 10^9 */
 }
 
-static unsigned long get_sample_period(void)
+static u64 get_sample_period(void)
 {
        /*
         * convert watchdog_thresh from seconds to ns
@@ -125,7 +125,7 @@ static unsigned long get_sample_period(void)
         * and hard thresholds) to increment before the
         * hardlockup detector generates a warning
         */
-       return get_softlockup_thresh() * (NSEC_PER_SEC / 5);
+       return get_softlockup_thresh() * ((u64)NSEC_PER_SEC / 5);
 }
 
 /* Commands for resetting the watchdog */
@@ -368,6 +368,9 @@ static void watchdog_disable(unsigned int cpu)
 {
        struct hrtimer *hrtimer = &__raw_get_cpu_var(watchdog_hrtimer);
 
+       if (!watchdog_enabled)
+               return;
+
        watchdog_set_prio(SCHED_NORMAL, 0);
        hrtimer_cancel(hrtimer);
        /* disable the perf event */
index d951daa..1dae900 100644 (file)
@@ -1361,8 +1361,19 @@ static void __queue_delayed_work(int cpu, struct workqueue_struct *wq,
 
        WARN_ON_ONCE(timer->function != delayed_work_timer_fn ||
                     timer->data != (unsigned long)dwork);
-       BUG_ON(timer_pending(timer));
-       BUG_ON(!list_empty(&work->entry));
+       WARN_ON_ONCE(timer_pending(timer));
+       WARN_ON_ONCE(!list_empty(&work->entry));
+
+       /*
+        * If @delay is 0, queue @dwork->work immediately.  This is for
+        * both optimization and correctness.  The earliest @timer can
+        * expire is on the closest next tick and delayed_work users depend
+        * on that there's no such delay when @delay is 0.
+        */
+       if (!delay) {
+               __queue_work(cpu, wq, &dwork->work);
+               return;
+       }
 
        timer_stats_timer_set_start_info(&dwork->timer);
 
@@ -1417,9 +1428,6 @@ bool queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
        bool ret = false;
        unsigned long flags;
 
-       if (!delay)
-               return queue_work_on(cpu, wq, &dwork->work);
-
        /* read the comment in __queue_work() */
        local_irq_save(flags);
 
@@ -2407,8 +2415,10 @@ static int rescuer_thread(void *__wq)
 repeat:
        set_current_state(TASK_INTERRUPTIBLE);
 
-       if (kthread_should_stop())
+       if (kthread_should_stop()) {
+               __set_current_state(TASK_RUNNING);
                return 0;
+       }
 
        /*
         * See whether any cpu is asking for help.  Unbounded
@@ -2982,7 +2992,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);
 
index 821a162..a08b791 100644 (file)
@@ -163,7 +163,7 @@ $(obj)/crc32table.h: $(obj)/gen_crc32table
 #
 obj-$(CONFIG_OID_REGISTRY) += oid_registry.o
 
-$(obj)/oid_registry.c: $(obj)/oid_registry_data.c
+$(obj)/oid_registry.o: $(obj)/oid_registry_data.c
 
 $(obj)/oid_registry_data.c: $(srctree)/include/linux/oid_registry.h \
                            $(src)/build_OID_registry
index de2c8b5..5293d24 100644 (file)
@@ -91,7 +91,7 @@ next_tag:
 
        /* Extract the length */
        len = data[dp++];
-       if (len < 0x7f) {
+       if (len <= 0x7f) {
                dp += len;
                goto next_tag;
        }
index b9087bf..d84beb9 100644 (file)
@@ -264,7 +264,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 +293,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;
index ca208a9..5492043 100644 (file)
@@ -178,7 +178,7 @@ int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phy
        struct gen_pool_chunk *chunk;
        int nbits = size >> pool->min_alloc_order;
        int nbytes = sizeof(struct gen_pool_chunk) +
-                               (nbits + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
+                               BITS_TO_LONGS(nbits) * sizeof(long);
 
        chunk = kmalloc_node(nbytes, GFP_KERNEL | __GFP_ZERO, nid);
        if (unlikely(chunk == NULL))
index 678ce4f..095ab15 100644 (file)
@@ -641,7 +641,14 @@ do { \
        **************  MIPS  *****************
        ***************************************/
 #if defined(__mips__) && W_TYPE_SIZE == 32
-#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7
+#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4
+#define umul_ppmm(w1, w0, u, v)                        \
+do {                                           \
+       UDItype __ll = (UDItype)(u) * (v);      \
+       w1 = __ll >> 32;                        \
+       w0 = __ll;                              \
+} while (0)
+#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7
 #define umul_ppmm(w1, w0, u, v) \
        __asm__ ("multu %2,%3" \
        : "=l" ((USItype)(w0)), \
@@ -666,7 +673,15 @@ do { \
        **************  MIPS/64  **************
        ***************************************/
 #if (defined(__mips) && __mips >= 3) && W_TYPE_SIZE == 64
-#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7
+#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4
+#define umul_ppmm(w1, w0, u, v) \
+do {                                                                   \
+       typedef unsigned int __ll_UTItype __attribute__((mode(TI)));    \
+       __ll_UTItype __ll = (__ll_UTItype)(u) * (v);                    \
+       w1 = __ll >> 64;                                                \
+       w0 = __ll;                                                      \
+} while (0)
+#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7
 #define umul_ppmm(w1, w0, u, v) \
        __asm__ ("dmultu %2,%3" \
        : "=l" ((UDItype)(w0)), \
index 434be4a..f468185 100644 (file)
@@ -198,8 +198,6 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
                        int order = ilog2(BITS_PER_LONG);
 
                        __free_pages_bootmem(pfn_to_page(start), order);
-                       fixup_zone_present_pages(page_to_nid(pfn_to_page(start)),
-                                       start, start + BITS_PER_LONG);
                        count += BITS_PER_LONG;
                        start += BITS_PER_LONG;
                } else {
@@ -210,9 +208,6 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
                                if (vec & 1) {
                                        page = pfn_to_page(start + off);
                                        __free_pages_bootmem(page, 0);
-                                       fixup_zone_present_pages(
-                                               page_to_nid(page),
-                                               start + off, start + off + 1);
                                        count++;
                                }
                                vec >>= 1;
@@ -226,11 +221,8 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
        pages = bdata->node_low_pfn - bdata->node_min_pfn;
        pages = bootmem_bootmap_pages(pages);
        count += pages;
-       while (pages--) {
-               fixup_zone_present_pages(page_to_nid(page),
-                               page_to_pfn(page), page_to_pfn(page) + 1);
+       while (pages--)
                __free_pages_bootmem(page++, 0);
-       }
 
        bdebug("nid=%td released=%lx\n", bdata - bootmem_node_data, count);
 
index 2c4ce17..694eaab 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)
@@ -713,7 +713,15 @@ static void isolate_freepages(struct zone *zone,
 
                /* Found a block suitable for isolating free pages from */
                isolated = 0;
-               end_pfn = min(pfn + pageblock_nr_pages, zone_end_pfn);
+
+               /*
+                * As pfn may not start aligned, pfn+pageblock_nr_page
+                * may cross a MAX_ORDER_NR_PAGES boundary and miss
+                * a pfn_valid check. Ensure isolate_freepages_block()
+                * only scans within a pageblock
+                */
+               end_pfn = ALIGN(pfn + 1, pageblock_nr_pages);
+               end_pfn = min(end_pfn, zone_end_pfn);
                isolated = isolate_freepages_block(cc, pfn, end_pfn,
                                                   freelist, false);
                nr_freepages += isolated;
index c5ab33b..da1b0f0 100644 (file)
@@ -50,7 +50,6 @@ struct dma_pool {             /* the pool */
        size_t allocation;
        size_t boundary;
        char name[32];
-       wait_queue_head_t waitq;
        struct list_head pools;
 };
 
@@ -62,8 +61,6 @@ struct dma_page {             /* cacheable header for 'allocation' bytes */
        unsigned int offset;
 };
 
-#define        POOL_TIMEOUT_JIFFIES    ((100 /* msec */ * HZ) / 1000)
-
 static DEFINE_MUTEX(pools_lock);
 
 static ssize_t
@@ -172,7 +169,6 @@ struct dma_pool *dma_pool_create(const char *name, struct device *dev,
        retval->size = size;
        retval->boundary = boundary;
        retval->allocation = allocation;
-       init_waitqueue_head(&retval->waitq);
 
        if (dev) {
                int ret;
@@ -227,7 +223,6 @@ static struct dma_page *pool_alloc_page(struct dma_pool *pool, gfp_t mem_flags)
                memset(page->vaddr, POOL_POISON_FREED, pool->allocation);
 #endif
                pool_initialise_page(pool, page);
-               list_add(&page->page_list, &pool->page_list);
                page->in_use = 0;
                page->offset = 0;
        } else {
@@ -315,30 +310,21 @@ void *dma_pool_alloc(struct dma_pool *pool, gfp_t mem_flags,
        might_sleep_if(mem_flags & __GFP_WAIT);
 
        spin_lock_irqsave(&pool->lock, flags);
- restart:
        list_for_each_entry(page, &pool->page_list, page_list) {
                if (page->offset < pool->allocation)
                        goto ready;
        }
-       page = pool_alloc_page(pool, GFP_ATOMIC);
-       if (!page) {
-               if (mem_flags & __GFP_WAIT) {
-                       DECLARE_WAITQUEUE(wait, current);
 
-                       __set_current_state(TASK_UNINTERRUPTIBLE);
-                       __add_wait_queue(&pool->waitq, &wait);
-                       spin_unlock_irqrestore(&pool->lock, flags);
+       /* pool_alloc_page() might sleep, so temporarily drop &pool->lock */
+       spin_unlock_irqrestore(&pool->lock, flags);
 
-                       schedule_timeout(POOL_TIMEOUT_JIFFIES);
+       page = pool_alloc_page(pool, mem_flags);
+       if (!page)
+               return NULL;
 
-                       spin_lock_irqsave(&pool->lock, flags);
-                       __remove_wait_queue(&pool->waitq, &wait);
-                       goto restart;
-               }
-               retval = NULL;
-               goto done;
-       }
+       spin_lock_irqsave(&pool->lock, flags);
 
+       list_add(&page->page_list, &pool->page_list);
  ready:
        page->in_use++;
        offset = page->offset;
@@ -348,7 +334,6 @@ void *dma_pool_alloc(struct dma_pool *pool, gfp_t mem_flags,
 #ifdef DMAPOOL_DEBUG
        memset(retval, POOL_POISON_ALLOCATED, pool->size);
 #endif
- done:
        spin_unlock_irqrestore(&pool->lock, flags);
        return retval;
 }
@@ -435,8 +420,6 @@ void dma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t dma)
        page->in_use--;
        *(int *)vaddr = page->offset;
        page->offset = offset;
-       if (waitqueue_active(&pool->waitq))
-               wake_up_locked(&pool->waitq);
        /*
         * Resist a temptation to do
         *    if (!is_page_busy(page)) pool_free_page(pool, page);
index 3899a86..a0aaf0e 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 d517cd1..2da13a5 100644 (file)
@@ -98,7 +98,7 @@ struct page *kmap_to_page(void *vaddr)
 {
        unsigned long addr = (unsigned long)vaddr;
 
-       if (addr >= PKMAP_ADDR(0) && addr <= PKMAP_ADDR(LAST_PKMAP)) {
+       if (addr >= PKMAP_ADDR(0) && addr < PKMAP_ADDR(LAST_PKMAP)) {
                int i = (addr - PKMAP_ADDR(0)) >> PAGE_SHIFT;
                return pte_page(pkmap_page_table[i]);
        }
index a863af2..40f17c3 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/khugepaged.h>
 #include <linux/freezer.h>
 #include <linux/mman.h>
+#include <linux/pagemap.h>
 #include <asm/tlb.h>
 #include <asm/pgalloc.h>
 #include "internal.h"
index 931eef1..6259055 100644 (file)
@@ -930,6 +930,30 @@ int __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t si
        return memblock_overlaps_region(&memblock.reserved, base, size) >= 0;
 }
 
+void __init_memblock memblock_trim_memory(phys_addr_t align)
+{
+       int i;
+       phys_addr_t start, end, orig_start, orig_end;
+       struct memblock_type *mem = &memblock.memory;
+
+       for (i = 0; i < mem->cnt; i++) {
+               orig_start = mem->regions[i].base;
+               orig_end = mem->regions[i].base + mem->regions[i].size;
+               start = round_up(orig_start, align);
+               end = round_down(orig_end, align);
+
+               if (start == orig_start && end == orig_end)
+                       continue;
+
+               if (start < end) {
+                       mem->regions[i].base = start;
+                       mem->regions[i].size = end - start;
+               } else {
+                       memblock_remove_region(mem, i);
+                       i--;
+               }
+       }
+}
 
 void __init_memblock memblock_set_current_limit(phys_addr_t limit)
 {
index 7acf43b..dd39ba0 100644 (file)
@@ -1055,12 +1055,24 @@ struct lruvec *mem_cgroup_zone_lruvec(struct zone *zone,
                                      struct mem_cgroup *memcg)
 {
        struct mem_cgroup_per_zone *mz;
+       struct lruvec *lruvec;
 
-       if (mem_cgroup_disabled())
-               return &zone->lruvec;
+       if (mem_cgroup_disabled()) {
+               lruvec = &zone->lruvec;
+               goto out;
+       }
 
        mz = mem_cgroup_zoneinfo(memcg, zone_to_nid(zone), zone_idx(zone));
-       return &mz->lruvec;
+       lruvec = &mz->lruvec;
+out:
+       /*
+        * Since a node can be onlined after the mem_cgroup was created,
+        * we have to be prepared to initialize lruvec->zone here;
+        * and if offlined then reonlined, we need to reinitialize it.
+        */
+       if (unlikely(lruvec->zone != zone))
+               lruvec->zone = zone;
+       return lruvec;
 }
 
 /*
@@ -1087,9 +1099,12 @@ struct lruvec *mem_cgroup_page_lruvec(struct page *page, struct zone *zone)
        struct mem_cgroup_per_zone *mz;
        struct mem_cgroup *memcg;
        struct page_cgroup *pc;
+       struct lruvec *lruvec;
 
-       if (mem_cgroup_disabled())
-               return &zone->lruvec;
+       if (mem_cgroup_disabled()) {
+               lruvec = &zone->lruvec;
+               goto out;
+       }
 
        pc = lookup_page_cgroup(page);
        memcg = pc->mem_cgroup;
@@ -1107,7 +1122,16 @@ struct lruvec *mem_cgroup_page_lruvec(struct page *page, struct zone *zone)
                pc->mem_cgroup = memcg = root_mem_cgroup;
 
        mz = page_cgroup_zoneinfo(memcg, page);
-       return &mz->lruvec;
+       lruvec = &mz->lruvec;
+out:
+       /*
+        * Since a node can be onlined after the mem_cgroup was created,
+        * we have to be prepared to initialize lruvec->zone here;
+        * and if offlined then reonlined, we need to reinitialize it.
+        */
+       if (unlikely(lruvec->zone != zone))
+               lruvec->zone = zone;
+       return lruvec;
 }
 
 /**
@@ -1452,17 +1476,26 @@ static int mem_cgroup_count_children(struct mem_cgroup *memcg)
 static u64 mem_cgroup_get_limit(struct mem_cgroup *memcg)
 {
        u64 limit;
-       u64 memsw;
 
        limit = res_counter_read_u64(&memcg->res, RES_LIMIT);
-       limit += total_swap_pages << PAGE_SHIFT;
 
-       memsw = res_counter_read_u64(&memcg->memsw, RES_LIMIT);
        /*
-        * If memsw is finite and limits the amount of swap space available
-        * to this memcg, return that limit.
+        * Do not consider swap space if we cannot swap due to swappiness
         */
-       return min(limit, memsw);
+       if (mem_cgroup_swappiness(memcg)) {
+               u64 memsw;
+
+               limit += total_swap_pages << PAGE_SHIFT;
+               memsw = res_counter_read_u64(&memcg->memsw, RES_LIMIT);
+
+               /*
+                * If memsw is finite and limits the amount of swap space
+                * available to this memcg, return that limit.
+                */
+               limit = min(limit, memsw);
+       }
+
+       return limit;
 }
 
 void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask,
@@ -3688,17 +3721,17 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
 static bool mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
                                int node, int zid, enum lru_list lru)
 {
-       struct mem_cgroup_per_zone *mz;
+       struct lruvec *lruvec;
        unsigned long flags, loop;
        struct list_head *list;
        struct page *busy;
        struct zone *zone;
 
        zone = &NODE_DATA(node)->node_zones[zid];
-       mz = mem_cgroup_zoneinfo(memcg, node, zid);
-       list = &mz->lruvec.lists[lru];
+       lruvec = mem_cgroup_zone_lruvec(zone, memcg);
+       list = &lruvec->lists[lru];
 
-       loop = mz->lru_size[lru];
+       loop = mem_cgroup_get_lru_size(lruvec, lru);
        /* give some margin against EBUSY etc...*/
        loop += 256;
        busy = NULL;
@@ -4736,7 +4769,7 @@ static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node)
 
        for (zone = 0; zone < MAX_NR_ZONES; zone++) {
                mz = &pn->zoneinfo[zone];
-               lruvec_init(&mz->lruvec, &NODE_DATA(node)->node_zones[zone]);
+               lruvec_init(&mz->lruvec);
                mz->usage_in_excess = 0;
                mz->on_tree = false;
                mz->memcg = memcg;
index 6c5899b..8b20278 100644 (file)
@@ -1476,9 +1476,17 @@ int soft_offline_page(struct page *page, int flags)
 {
        int ret;
        unsigned long pfn = page_to_pfn(page);
+       struct page *hpage = compound_trans_head(page);
 
        if (PageHuge(page))
                return soft_offline_huge_page(page, flags);
+       if (PageTransHuge(hpage)) {
+               if (PageAnon(hpage) && unlikely(split_huge_page(hpage))) {
+                       pr_info("soft offline: %#lx: failed to split THP\n",
+                               pfn);
+                       return -EBUSY;
+               }
+       }
 
        ret = get_any_page(page, pfn, flags);
        if (ret < 0)
index fb135ba..221fc9f 100644 (file)
@@ -2527,9 +2527,8 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
        int ret = 0;
        int page_mkwrite = 0;
        struct page *dirty_page = NULL;
-       unsigned long mmun_start;       /* For mmu_notifiers */
-       unsigned long mmun_end;         /* For mmu_notifiers */
-       bool mmun_called = false;       /* For mmu_notifiers */
+       unsigned long mmun_start = 0;   /* For mmu_notifiers */
+       unsigned long mmun_end = 0;     /* For mmu_notifiers */
 
        old_page = vm_normal_page(vma, address, orig_pte);
        if (!old_page) {
@@ -2708,8 +2707,7 @@ gotten:
                goto oom_free_new;
 
        mmun_start  = address & PAGE_MASK;
-       mmun_end    = (address & PAGE_MASK) + PAGE_SIZE;
-       mmun_called = true;
+       mmun_end    = mmun_start + PAGE_SIZE;
        mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
 
        /*
@@ -2778,7 +2776,7 @@ gotten:
                page_cache_release(new_page);
 unlock:
        pte_unmap_unlock(page_table, ptl);
-       if (mmun_called)
+       if (mmun_end > mmun_start)
                mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
        if (old_page) {
                /*
index 56b758a..e4eeaca 100644 (file)
@@ -106,7 +106,6 @@ static void get_page_bootmem(unsigned long info,  struct page *page,
 void __ref put_page_bootmem(struct page *page)
 {
        unsigned long type;
-       struct zone *zone;
 
        type = (unsigned long) page->lru.next;
        BUG_ON(type < MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE ||
@@ -117,12 +116,6 @@ void __ref put_page_bootmem(struct page *page)
                set_page_private(page, 0);
                INIT_LIST_HEAD(&page->lru);
                __free_pages_bootmem(page, 0);
-
-               zone = page_zone(page);
-               zone_span_writelock(zone);
-               zone->present_pages++;
-               zone_span_writeunlock(zone);
-               totalram_pages++;
        }
 
 }
index 0b78fb9..4ea600d 100644 (file)
@@ -1536,9 +1536,8 @@ asmlinkage long compat_sys_mbind(compat_ulong_t start, compat_ulong_t len,
  *
  * Returns effective policy for a VMA at specified address.
  * Falls back to @task or system default policy, as necessary.
- * Current or other task's task mempolicy and non-shared vma policies
- * are protected by the task's mmap_sem, which must be held for read by
- * the caller.
+ * Current or other task's task mempolicy and non-shared vma policies must be
+ * protected by task_lock(task) by the caller.
  * Shared policies [those marked as MPOL_F_SHARED] require an extra reference
  * count--added by the get_policy() vm_op, as appropriate--to protect against
  * freeing by another task.  It is the caller's responsibility to free the
@@ -2038,28 +2037,6 @@ struct mempolicy *__mpol_dup(struct mempolicy *old)
        return new;
 }
 
-/*
- * If *frompol needs [has] an extra ref, copy *frompol to *tompol ,
- * eliminate the * MPOL_F_* flags that require conditional ref and
- * [NOTE!!!] drop the extra ref.  Not safe to reference *frompol directly
- * after return.  Use the returned value.
- *
- * Allows use of a mempolicy for, e.g., multiple allocations with a single
- * policy lookup, even if the policy needs/has extra ref on lookup.
- * shmem_readahead needs this.
- */
-struct mempolicy *__mpol_cond_copy(struct mempolicy *tompol,
-                                               struct mempolicy *frompol)
-{
-       if (!mpol_needs_cond_ref(frompol))
-               return frompol;
-
-       *tompol = *frompol;
-       tompol->flags &= ~MPOL_F_SHARED;        /* copy doesn't need unref */
-       __mpol_put(frompol);
-       return tompol;
-}
-
 /* Slow path of a mempolicy comparison */
 bool __mpol_equal(struct mempolicy *a, struct mempolicy *b)
 {
index 2d94235..9a796c4 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -334,8 +334,10 @@ void validate_mm(struct mm_struct *mm)
        struct vm_area_struct *vma = mm->mmap;
        while (vma) {
                struct anon_vma_chain *avc;
+               vma_lock_anon_vma(vma);
                list_for_each_entry(avc, &vma->anon_vma_chain, same_vma)
                        anon_vma_interval_tree_verify(avc);
+               vma_unlock_anon_vma(vma);
                vma = vma->vm_next;
                i++;
        }
index 479a1e7..8a5ac8c 100644 (file)
@@ -196,28 +196,28 @@ static int do_mmu_notifier_register(struct mmu_notifier *mn,
        BUG_ON(atomic_read(&mm->mm_users) <= 0);
 
        /*
-       * Verify that mmu_notifier_init() already run and the global srcu is
-       * initialized.
-       */
+        * Verify that mmu_notifier_init() already run and the global srcu is
+        * initialized.
+        */
        BUG_ON(!srcu.per_cpu_ref);
 
+       ret = -ENOMEM;
+       mmu_notifier_mm = kmalloc(sizeof(struct mmu_notifier_mm), GFP_KERNEL);
+       if (unlikely(!mmu_notifier_mm))
+               goto out;
+
        if (take_mmap_sem)
                down_write(&mm->mmap_sem);
        ret = mm_take_all_locks(mm);
        if (unlikely(ret))
-               goto out;
+               goto out_clean;
 
        if (!mm_has_notifiers(mm)) {
-               mmu_notifier_mm = kmalloc(sizeof(struct mmu_notifier_mm),
-                                       GFP_KERNEL);
-               if (unlikely(!mmu_notifier_mm)) {
-                       ret = -ENOMEM;
-                       goto out_of_mem;
-               }
                INIT_HLIST_HEAD(&mmu_notifier_mm->list);
                spin_lock_init(&mmu_notifier_mm->lock);
 
                mm->mmu_notifier_mm = mmu_notifier_mm;
+               mmu_notifier_mm = NULL;
        }
        atomic_inc(&mm->mm_count);
 
@@ -233,12 +233,12 @@ static int do_mmu_notifier_register(struct mmu_notifier *mn,
        hlist_add_head(&mn->hlist, &mm->mmu_notifier_mm->list);
        spin_unlock(&mm->mmu_notifier_mm->lock);
 
-out_of_mem:
        mm_drop_all_locks(mm);
-out:
+out_clean:
        if (take_mmap_sem)
                up_write(&mm->mmap_sem);
-
+       kfree(mmu_notifier_mm);
+out:
        BUG_ON(atomic_read(&mm->mm_users) <= 0);
        return ret;
 }
index 3cef80f..4596d81 100644 (file)
@@ -87,7 +87,7 @@ int memmap_valid_within(unsigned long pfn,
 }
 #endif /* CONFIG_ARCH_HAS_HOLES_MEMORYMODEL */
 
-void lruvec_init(struct lruvec *lruvec, struct zone *zone)
+void lruvec_init(struct lruvec *lruvec)
 {
        enum lru_list lru;
 
@@ -95,8 +95,4 @@ void lruvec_init(struct lruvec *lruvec, struct zone *zone)
 
        for_each_lru(lru)
                INIT_LIST_HEAD(&lruvec->lists[lru]);
-
-#ifdef CONFIG_MEMCG
-       lruvec->zone = zone;
-#endif
 }
index 714d5d6..bd82f6b 100644 (file)
@@ -116,8 +116,6 @@ static unsigned long __init __free_memory_core(phys_addr_t start,
                return 0;
 
        __free_pages_memory(start_pfn, end_pfn);
-       fixup_zone_present_pages(pfn_to_nid(start >> PAGE_SHIFT),
-                       start_pfn, end_pfn);
 
        return end_pfn - start_pfn;
 }
@@ -128,7 +126,6 @@ unsigned long __init free_low_memory_core_early(int nodeid)
        phys_addr_t start, end, size;
        u64 i;
 
-       reset_zone_present_pages();
        for_each_free_mem_range(i, MAX_NUMNODES, &start, &end, NULL)
                count += __free_memory_core(start, end);
 
index bb90971..7e208f0 100644 (file)
@@ -1405,7 +1405,7 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype)
 
        mt = get_pageblock_migratetype(page);
        if (unlikely(mt != MIGRATE_ISOLATE))
-               __mod_zone_freepage_state(zone, -(1UL << order), mt);
+               __mod_zone_freepage_state(zone, -(1UL << alloc_order), mt);
 
        if (alloc_order != order)
                expand(zone, page, alloc_order, order,
@@ -1422,7 +1422,7 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype)
                }
        }
 
-       return 1UL << order;
+       return 1UL << alloc_order;
 }
 
 /*
@@ -1809,10 +1809,10 @@ static void __paginginit init_zone_allows_reclaim(int nid)
        int i;
 
        for_each_online_node(i)
-               if (node_distance(nid, i) <= RECLAIM_DISTANCE) {
+               if (node_distance(nid, i) <= RECLAIM_DISTANCE)
                        node_set(i, NODE_DATA(nid)->reclaim_nodes);
+               else
                        zone_reclaim_mode = 1;
-               }
 }
 
 #else  /* CONFIG_NUMA */
@@ -2416,8 +2416,9 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
                goto nopage;
 
 restart:
-       wake_all_kswapd(order, zonelist, high_zoneidx,
-                                       zone_idx(preferred_zone));
+       if (!(gfp_mask & __GFP_NO_KSWAPD))
+               wake_all_kswapd(order, zonelist, high_zoneidx,
+                                               zone_idx(preferred_zone));
 
        /*
         * OK, we're below the kswapd watermark and have kicked background
@@ -2494,7 +2495,7 @@ rebalance:
         * system then fail the allocation instead of entering direct reclaim.
         */
        if ((deferred_compaction || contended_compaction) &&
-           (gfp_mask & (__GFP_MOVABLE|__GFP_REPEAT)) == __GFP_MOVABLE)
+                                               (gfp_mask & __GFP_NO_KSWAPD))
                goto nopage;
 
        /* Try direct reclaim and then allocating */
@@ -4505,7 +4506,7 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat,
                zone->zone_pgdat = pgdat;
 
                zone_pcp_init(zone);
-               lruvec_init(&zone->lruvec, zone);
+               lruvec_init(&zone->lruvec);
                if (!size)
                        continue;
 
@@ -5825,7 +5826,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)
@@ -6098,37 +6099,3 @@ void dump_page(struct page *page)
        dump_page_flags(page->flags);
        mem_cgroup_print_bad_page(page);
 }
-
-/* reset zone->present_pages */
-void reset_zone_present_pages(void)
-{
-       struct zone *z;
-       int i, nid;
-
-       for_each_node_state(nid, N_HIGH_MEMORY) {
-               for (i = 0; i < MAX_NR_ZONES; i++) {
-                       z = NODE_DATA(nid)->node_zones + i;
-                       z->present_pages = 0;
-               }
-       }
-}
-
-/* calculate zone's present pages in buddy system */
-void fixup_zone_present_pages(int nid, unsigned long start_pfn,
-                               unsigned long end_pfn)
-{
-       struct zone *z;
-       unsigned long zone_start_pfn, zone_end_pfn;
-       int i;
-
-       for (i = 0; i < MAX_NR_ZONES; i++) {
-               z = NODE_DATA(nid)->node_zones + i;
-               zone_start_pfn = z->zone_start_pfn;
-               zone_end_pfn = zone_start_pfn + z->spanned_pages;
-
-               /* if the two regions intersect */
-               if (!(zone_start_pfn >= end_pfn || zone_end_pfn <= start_pfn))
-                       z->present_pages += min(end_pfn, zone_end_pfn) -
-                                           max(start_pfn, zone_start_pfn);
-       }
-}
index 7df7984..2ee1ef0 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -56,6 +56,7 @@
 #include <linux/mmu_notifier.h>
 #include <linux/migrate.h>
 #include <linux/hugetlb.h>
+#include <linux/backing-dev.h>
 
 #include <asm/tlbflush.h>
 
@@ -926,11 +927,8 @@ int page_mkclean(struct page *page)
 
        if (page_mapped(page)) {
                struct address_space *mapping = page_mapping(page);
-               if (mapping) {
+               if (mapping)
                        ret = page_mkclean_file(mapping, page);
-                       if (page_test_and_clear_dirty(page_to_pfn(page), 1))
-                               ret = 1;
-               }
        }
 
        return ret;
@@ -1116,6 +1114,7 @@ void page_add_file_rmap(struct page *page)
  */
 void page_remove_rmap(struct page *page)
 {
+       struct address_space *mapping = page_mapping(page);
        bool anon = PageAnon(page);
        bool locked;
        unsigned long flags;
@@ -1138,8 +1137,19 @@ void page_remove_rmap(struct page *page)
         * this if the page is anon, so about to be freed; but perhaps
         * not if it's in swapcache - there might be another pte slot
         * containing the swap entry, but page not yet written to swap.
+        *
+        * And we can skip it on file pages, so long as the filesystem
+        * participates in dirty tracking; but need to catch shm and tmpfs
+        * and ramfs pages which have been modified since creation by read
+        * fault.
+        *
+        * Note that mapping must be decided above, before decrementing
+        * mapcount (which luckily provides a barrier): once page is unmapped,
+        * it could be truncated and page->mapping reset to NULL at any moment.
+        * Note also that we are relying on page_mapping(page) to set mapping
+        * to &swapper_space when PageSwapCache(page).
         */
-       if ((!anon || PageSwapCache(page)) &&
+       if (mapping && !mapping_cap_account_dirty(mapping) &&
            page_test_and_clear_dirty(page_to_pfn(page), 1))
                set_page_dirty(page);
        /*
index 67afba5..50c5b8f 100644 (file)
@@ -643,7 +643,7 @@ static void shmem_evict_inode(struct inode *inode)
                kfree(info->symlink);
 
        simple_xattrs_free(&info->xattrs);
-       BUG_ON(inode->i_blocks);
+       WARN_ON(inode->i_blocks);
        shmem_free_inode(inode->i_sb);
        clear_inode(inode);
 }
@@ -910,25 +910,29 @@ static struct mempolicy *shmem_get_sbmpol(struct shmem_sb_info *sbinfo)
 static struct page *shmem_swapin(swp_entry_t swap, gfp_t gfp,
                        struct shmem_inode_info *info, pgoff_t index)
 {
-       struct mempolicy mpol, *spol;
        struct vm_area_struct pvma;
-
-       spol = mpol_cond_copy(&mpol,
-                       mpol_shared_policy_lookup(&info->policy, index));
+       struct page *page;
 
        /* Create a pseudo vma that just contains the policy */
        pvma.vm_start = 0;
        /* Bias interleave by inode number to distribute better across nodes */
        pvma.vm_pgoff = index + info->vfs_inode.i_ino;
        pvma.vm_ops = NULL;
-       pvma.vm_policy = spol;
-       return swapin_readahead(swap, gfp, &pvma, 0);
+       pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, index);
+
+       page = swapin_readahead(swap, gfp, &pvma, 0);
+
+       /* Drop reference taken by mpol_shared_policy_lookup() */
+       mpol_cond_put(pvma.vm_policy);
+
+       return page;
 }
 
 static struct page *shmem_alloc_page(gfp_t gfp,
                        struct shmem_inode_info *info, pgoff_t index)
 {
        struct vm_area_struct pvma;
+       struct page *page;
 
        /* Create a pseudo vma that just contains the policy */
        pvma.vm_start = 0;
@@ -937,10 +941,12 @@ static struct page *shmem_alloc_page(gfp_t gfp,
        pvma.vm_ops = NULL;
        pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, index);
 
-       /*
-        * alloc_page_vma() will drop the shared policy reference
-        */
-       return alloc_page_vma(gfp, &pvma, 0);
+       page = alloc_page_vma(gfp, &pvma, 0);
+
+       /* Drop reference taken by mpol_shared_policy_lookup() */
+       mpol_cond_put(pvma.vm_policy);
+
+       return page;
 }
 #else /* !CONFIG_NUMA */
 #ifdef CONFIG_TMPFS
@@ -1145,8 +1151,20 @@ repeat:
                if (!error) {
                        error = shmem_add_to_page_cache(page, mapping, index,
                                                gfp, swp_to_radix_entry(swap));
-                       /* We already confirmed swap, and make no allocation */
-                       VM_BUG_ON(error);
+                       /*
+                        * We already confirmed swap under page lock, and make
+                        * no memory allocation here, so usually no possibility
+                        * of error; but free_swap_and_cache() only trylocks a
+                        * page, so it is just possible that the entry has been
+                        * truncated or holepunched since swap was confirmed.
+                        * shmem_undo_range() will have done some of the
+                        * unaccounting, now delete_from_swap_cache() will do
+                        * the rest (including mem_cgroup_uncharge_swapcache).
+                        * Reset swap.val? No, leave it so "failed" goes back to
+                        * "repeat": reading a hole and writing should succeed.
+                        */
+                       if (error)
+                               delete_from_swap_cache(page);
                }
                if (error)
                        goto failed;
index a08e468..1e921c5 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 fac95f2..a83de2f 100644 (file)
@@ -617,7 +617,7 @@ static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages)
 {
        return; /* XXX: Not implemented yet */
 }
-static void free_map_bootmem(struct page *page, unsigned long nr_pages)
+static void free_map_bootmem(struct page *memmap, unsigned long nr_pages)
 {
 }
 #else
@@ -658,10 +658,11 @@ static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages)
                           get_order(sizeof(struct page) * nr_pages));
 }
 
-static void free_map_bootmem(struct page *page, unsigned long nr_pages)
+static void free_map_bootmem(struct page *memmap, unsigned long nr_pages)
 {
        unsigned long maps_section_nr, removing_section_nr, i;
        unsigned long magic;
+       struct page *page = virt_to_page(memmap);
 
        for (i = 0; i < nr_pages; i++, page++) {
                magic = (unsigned long) page->lru.next;
@@ -710,13 +711,10 @@ static void free_section_usemap(struct page *memmap, unsigned long *usemap)
         */
 
        if (memmap) {
-               struct page *memmap_page;
-               memmap_page = virt_to_page(memmap);
-
                nr_pages = PAGE_ALIGN(PAGES_PER_SECTION * sizeof(struct page))
                        >> PAGE_SHIFT;
 
-               free_map_bootmem(memmap_page, nr_pages);
+               free_map_bootmem(memmap, nr_pages);
        }
 }
 
index 71cd288..f91a255 100644 (file)
@@ -1494,9 +1494,8 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
        BUG_ON(!current->mm);
 
        pathname = getname(specialfile);
-       err = PTR_ERR(pathname);
        if (IS_ERR(pathname))
-               goto out;
+               return PTR_ERR(pathname);
 
        victim = file_open_name(pathname, O_RDWR|O_LARGEFILE, 0);
        err = PTR_ERR(victim);
@@ -1608,6 +1607,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
 out_dput:
        filp_close(victim, NULL);
 out:
+       putname(pathname);
        return err;
 }
 
index 2624edc..b7ed376 100644 (file)
@@ -1760,28 +1760,6 @@ static bool in_reclaim_compaction(struct scan_control *sc)
        return false;
 }
 
-#ifdef CONFIG_COMPACTION
-/*
- * If compaction is deferred for sc->order then scale the number of pages
- * reclaimed based on the number of consecutive allocation failures
- */
-static unsigned long scale_for_compaction(unsigned long pages_for_compaction,
-                       struct lruvec *lruvec, struct scan_control *sc)
-{
-       struct zone *zone = lruvec_zone(lruvec);
-
-       if (zone->compact_order_failed <= sc->order)
-               pages_for_compaction <<= zone->compact_defer_shift;
-       return pages_for_compaction;
-}
-#else
-static unsigned long scale_for_compaction(unsigned long pages_for_compaction,
-                       struct lruvec *lruvec, struct scan_control *sc)
-{
-       return pages_for_compaction;
-}
-#endif
-
 /*
  * Reclaim/compaction is used for high-order allocation requests. It reclaims
  * order-0 pages before compacting the zone. should_continue_reclaim() returns
@@ -1829,9 +1807,6 @@ static inline bool should_continue_reclaim(struct lruvec *lruvec,
         * inactive lists are large enough, continue reclaiming
         */
        pages_for_compaction = (2UL << sc->order);
-
-       pages_for_compaction = scale_for_compaction(pages_for_compaction,
-                                                   lruvec, sc);
        inactive_lru_pages = get_lru_size(lruvec, LRU_INACTIVE_FILE);
        if (nr_swap_pages > 0)
                inactive_lru_pages += get_lru_size(lruvec, LRU_INACTIVE_ANON);
@@ -2232,9 +2207,12 @@ static bool pfmemalloc_watermark_ok(pg_data_t *pgdat)
  * Throttle direct reclaimers if backing storage is backed by the network
  * and the PFMEMALLOC reserve for the preferred node is getting dangerously
  * depleted. kswapd will continue to make progress and wake the processes
- * when the low watermark is reached
+ * when the low watermark is reached.
+ *
+ * Returns true if a fatal signal was delivered during throttling. If this
+ * happens, the page allocator should not consider triggering the OOM killer.
  */
-static void throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist,
+static bool throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist,
                                        nodemask_t *nodemask)
 {
        struct zone *zone;
@@ -2249,13 +2227,20 @@ static void throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist,
         * processes to block on log_wait_commit().
         */
        if (current->flags & PF_KTHREAD)
-               return;
+               goto out;
+
+       /*
+        * If a fatal signal is pending, this process should not throttle.
+        * It should return quickly so it can exit and free its memory
+        */
+       if (fatal_signal_pending(current))
+               goto out;
 
        /* Check if the pfmemalloc reserves are ok */
        first_zones_zonelist(zonelist, high_zoneidx, NULL, &zone);
        pgdat = zone->zone_pgdat;
        if (pfmemalloc_watermark_ok(pgdat))
-               return;
+               goto out;
 
        /* Account for the throttling */
        count_vm_event(PGSCAN_DIRECT_THROTTLE);
@@ -2271,12 +2256,20 @@ static void throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist,
        if (!(gfp_mask & __GFP_FS)) {
                wait_event_interruptible_timeout(pgdat->pfmemalloc_wait,
                        pfmemalloc_watermark_ok(pgdat), HZ);
-               return;
+
+               goto check_pending;
        }
 
        /* Throttle until kswapd wakes the process */
        wait_event_killable(zone->zone_pgdat->pfmemalloc_wait,
                pfmemalloc_watermark_ok(pgdat));
+
+check_pending:
+       if (fatal_signal_pending(current))
+               return true;
+
+out:
+       return false;
 }
 
 unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
@@ -2298,13 +2291,12 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
                .gfp_mask = sc.gfp_mask,
        };
 
-       throttle_direct_reclaim(gfp_mask, zonelist, nodemask);
-
        /*
-        * Do not enter reclaim if fatal signal is pending. 1 is returned so
-        * that the page allocator does not consider triggering OOM
+        * Do not enter reclaim if fatal signal was delivered while throttled.
+        * 1 is returned so that the page allocator does not OOM kill at this
+        * point.
         */
-       if (fatal_signal_pending(current))
+       if (throttle_direct_reclaim(gfp_mask, zonelist, nodemask))
                return 1;
 
        trace_mm_vmscan_direct_reclaim_begin(order,
@@ -2422,6 +2414,19 @@ static void age_active_anon(struct zone *zone, struct scan_control *sc)
        } while (memcg);
 }
 
+static bool zone_balanced(struct zone *zone, int order,
+                         unsigned long balance_gap, int classzone_idx)
+{
+       if (!zone_watermark_ok_safe(zone, order, high_wmark_pages(zone) +
+                                   balance_gap, classzone_idx, 0))
+               return false;
+
+       if (COMPACTION_BUILD && order && !compaction_suitable(zone, order))
+               return false;
+
+       return true;
+}
+
 /*
  * pgdat_balanced is used when checking if a node is balanced for high-order
  * allocations. Only zones that meet watermarks and are in a zone allowed
@@ -2500,8 +2505,7 @@ static bool prepare_kswapd_sleep(pg_data_t *pgdat, int order, long remaining,
                        continue;
                }
 
-               if (!zone_watermark_ok_safe(zone, order, high_wmark_pages(zone),
-                                                       i, 0))
+               if (!zone_balanced(zone, order, 0, i))
                        all_zones_ok = false;
                else
                        balanced += zone->present_pages;
@@ -2610,8 +2614,7 @@ loop_again:
                                break;
                        }
 
-                       if (!zone_watermark_ok_safe(zone, order,
-                                       high_wmark_pages(zone), 0, 0)) {
+                       if (!zone_balanced(zone, order, 0, 0)) {
                                end_zone = i;
                                break;
                        } else {
@@ -2687,9 +2690,8 @@ loop_again:
                                testorder = 0;
 
                        if ((buffer_heads_over_limit && is_highmem_idx(i)) ||
-                                   !zone_watermark_ok_safe(zone, testorder,
-                                       high_wmark_pages(zone) + balance_gap,
-                                       end_zone, 0)) {
+                           !zone_balanced(zone, testorder,
+                                          balance_gap, end_zone)) {
                                shrink_zone(zone, &sc);
 
                                reclaim_state->reclaimed_slab = 0;
@@ -2716,8 +2718,7 @@ loop_again:
                                continue;
                        }
 
-                       if (!zone_watermark_ok_safe(zone, testorder,
-                                       high_wmark_pages(zone), end_zone, 0)) {
+                       if (!zone_balanced(zone, testorder, 0, end_zone)) {
                                all_zones_ok = 0;
                                /*
                                 * We are still under min water mark.  This
@@ -2822,29 +2823,10 @@ out:
                        if (!populated_zone(zone))
                                continue;
 
-                       if (zone->all_unreclaimable &&
-                           sc.priority != DEF_PRIORITY)
-                               continue;
-
-                       /* Would compaction fail due to lack of free memory? */
-                       if (COMPACTION_BUILD &&
-                           compaction_suitable(zone, order) == COMPACT_SKIPPED)
-                               goto loop_again;
-
-                       /* Confirm the zone is balanced for order-0 */
-                       if (!zone_watermark_ok(zone, 0,
-                                       high_wmark_pages(zone), 0, 0)) {
-                               order = sc.order = 0;
-                               goto loop_again;
-                       }
-
                        /* Check if the memory needs to be defragmented. */
                        if (zone_watermark_ok(zone, order,
                                    low_wmark_pages(zone), *classzone_idx, 0))
                                zones_need_compaction = 0;
-
-                       /* If balanced, clear the congested flag */
-                       zone_clear_flag(zone, ZONE_CONGESTED);
                }
 
                if (zones_need_compaction)
@@ -3017,6 +2999,8 @@ static int kswapd(void *p)
                                                &balanced_classzone_idx);
                }
        }
+
+       current->reclaim_state = NULL;
        return 0;
 }
 
index 9096bcb..ee07072 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 fbbf1fa..65e06ab 100644 (file)
@@ -366,6 +366,13 @@ EXPORT_SYMBOL(vlan_vids_del_by_dev);
 
 bool vlan_uses_dev(const struct net_device *dev)
 {
-       return rtnl_dereference(dev->vlan_info) ? true : false;
+       struct vlan_info *vlan_info;
+
+       ASSERT_RTNL();
+
+       vlan_info = rtnl_dereference(dev->vlan_info);
+       if (!vlan_info)
+               return false;
+       return vlan_info->grp.nr_vlan_devs ? true : false;
 }
 EXPORT_SYMBOL(vlan_uses_dev);
index 0a9084a..fd8d5af 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 939fc01..376b4cc 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 b9a28d2..ce0684a 100644 (file)
@@ -325,6 +325,12 @@ void batadv_interface_rx(struct net_device *soft_iface,
 
        soft_iface->last_rx = jiffies;
 
+       /* Let the bridge loop avoidance check the packet. If will
+        * not handle it, we can safely push it up.
+        */
+       if (batadv_bla_rx(bat_priv, skb, vid, is_bcast))
+               goto out;
+
        if (orig_node)
                batadv_tt_add_temporary_global_entry(bat_priv, orig_node,
                                                     ethhdr->h_source);
@@ -332,12 +338,6 @@ void batadv_interface_rx(struct net_device *soft_iface,
        if (batadv_is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest))
                goto dropped;
 
-       /* Let the bridge loop avoidance check the packet. If will
-        * not handle it, we can safely push it up.
-        */
-       if (batadv_bla_rx(bat_priv, skb, vid, is_bcast))
-               goto out;
-
        netif_rx(skb);
        goto out;
 
index 112edd3..baae715 100644 (file)
@@ -769,6 +769,12 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
                 */
                tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_TEMP;
 
+               /* the change can carry possible "attribute" flags like the
+                * TT_CLIENT_WIFI, therefore they have to be copied in the
+                * client entry
+                */
+               tt_global_entry->common.flags |= flags;
+
                /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
                 * one originator left in the list and we previously received a
                 * delete + roaming change for this originator.
@@ -1496,7 +1502,7 @@ batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
 
                        memcpy(tt_change->addr, tt_common_entry->addr,
                               ETH_ALEN);
-                       tt_change->flags = BATADV_NO_FLAGS;
+                       tt_change->flags = tt_common_entry->flags;
 
                        tt_count++;
                        tt_change++;
@@ -2450,6 +2456,13 @@ bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
 {
        bool ret = false;
 
+       /* if the originator is a backbone node (meaning it belongs to the same
+        * LAN of this node) the temporary client must not be added because to
+        * reach such destination the node must use the LAN instead of the mesh
+        */
+       if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig))
+               goto out;
+
        if (!batadv_tt_global_add(bat_priv, orig_node, addr,
                                  BATADV_TT_CLIENT_TEMP,
                                  atomic_read(&orig_node->last_ttvn)))
index 2ed82ca..ac1e07a 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 8a0ce70..a0a2f97 100644 (file)
@@ -1754,11 +1754,11 @@ int hci_register_dev(struct hci_dev *hdev)
        if (hdev->dev_type != HCI_AMP)
                set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
 
-       schedule_work(&hdev->power_on);
-
        hci_notify(hdev, HCI_DEV_REG);
        hci_dev_hold(hdev);
 
+       schedule_work(&hdev->power_on);
+
        return id;
 
 err_wqueue:
index aa2ea0a..91de423 100644 (file)
@@ -326,7 +326,7 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
        struct hci_dev *d;
        size_t rp_len;
        u16 count;
-       int i, err;
+       int err;
 
        BT_DBG("sock %p", sk);
 
@@ -347,9 +347,7 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
                return -ENOMEM;
        }
 
-       rp->num_controllers = cpu_to_le16(count);
-
-       i = 0;
+       count = 0;
        list_for_each_entry(d, &hci_dev_list, list) {
                if (test_bit(HCI_SETUP, &d->dev_flags))
                        continue;
@@ -357,10 +355,13 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
                if (!mgmt_valid_hdev(d))
                        continue;
 
-               rp->index[i++] = cpu_to_le16(d->id);
+               rp->index[count++] = cpu_to_le16(d->id);
                BT_DBG("Added hci%u", d->id);
        }
 
+       rp->num_controllers = cpu_to_le16(count);
+       rp_len = sizeof(*rp) + (2 * count);
+
        read_unlock(&hci_dev_list_lock);
 
        err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
@@ -1366,6 +1367,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
                        continue;
 
                list_del(&match->list);
+               kfree(match);
                found++;
        }
 
index 8c225ef..a592337 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;
@@ -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)
@@ -265,7 +267,7 @@ static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send)
 
        clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->flags);
        mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type,
-                        hcon->dst_type, reason);
+                        hcon->dst_type, HCI_ERROR_AUTH_FAILURE);
 
        cancel_delayed_work_sync(&conn->security_timer);
 
index 6f74758..969b7cd 100644 (file)
@@ -1084,6 +1084,9 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
                op->sk = sk;
                op->ifindex = ifindex;
 
+               /* ifindex for timeout events w/o previous frame reception */
+               op->rx_ifindex = ifindex;
+
                /* initialize uninitialized (kzalloc) structure */
                hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
                op->timer.function = bcm_rx_timeout_handler;
index 159aa8b..3ef1759 100644 (file)
@@ -2300,10 +2300,11 @@ restart:
                        mutex_unlock(&con->mutex);
                        return;
                } else {
-                       con->ops->put(con);
                        dout("con_work %p FAILED to back off %lu\n", con,
                             con->delay);
+                       set_bit(CON_FLAG_BACKOFF, &con->flags);
                }
+               goto done;
        }
 
        if (con->state == CON_STATE_STANDBY) {
@@ -2749,7 +2750,8 @@ static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip)
                msg = con->ops->alloc_msg(con, hdr, skip);
                mutex_lock(&con->mutex);
                if (con->state != CON_STATE_OPEN) {
-                       ceph_msg_put(msg);
+                       if (msg)
+                               ceph_msg_put(msg);
                        return -EAGAIN;
                }
                con->in_msg = msg;
index 09cb3f6..e5942bf 100644 (file)
@@ -1666,7 +1666,7 @@ static inline int deliver_skb(struct sk_buff *skb,
 
 static inline bool skb_loop_sk(struct packet_type *ptype, struct sk_buff *skb)
 {
-       if (ptype->af_packet_priv == NULL)
+       if (!ptype->af_packet_priv || !skb->sk)
                return false;
 
        if (ptype->id_match)
@@ -2818,8 +2818,10 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb,
                if (unlikely(tcpu != next_cpu) &&
                    (tcpu == RPS_NO_CPU || !cpu_online(tcpu) ||
                     ((int)(per_cpu(softnet_data, tcpu).input_queue_head -
-                     rflow->last_qtail)) >= 0))
+                     rflow->last_qtail)) >= 0)) {
+                       tcpu = next_cpu;
                        rflow = set_rps_cpu(dev, skb, rflow, next_cpu);
+               }
 
                if (tcpu != RPS_NO_CPU && cpu_online(tcpu)) {
                        *rflowp = rflow;
@@ -3449,6 +3451,8 @@ static int napi_gro_complete(struct sk_buff *skb)
        struct list_head *head = &ptype_base[ntohs(type) & PTYPE_HASH_MASK];
        int err = -ENOENT;
 
+       BUILD_BUG_ON(sizeof(struct napi_gro_cb) > sizeof(skb->cb));
+
        if (NAPI_GRO_CB(skb)->count == 1) {
                skb_shinfo(skb)->gso_size = 0;
                goto out;
index 87cc17d..b079c7b 100644 (file)
@@ -319,7 +319,8 @@ int dev_addr_del(struct net_device *dev, const unsigned char *addr,
         */
        ha = list_first_entry(&dev->dev_addrs.list,
                              struct netdev_hw_addr, list);
-       if (ha->addr == dev->dev_addr && ha->refcount == 1)
+       if (!memcmp(ha->addr, addr, dev->addr_len) &&
+           ha->type == addr_type && ha->refcount == 1)
                return -ENOENT;
 
        err = __hw_addr_del(&dev->dev_addrs, addr, dev->addr_len,
index bcf02f6..017a8ba 100644 (file)
@@ -429,6 +429,17 @@ static struct attribute_group netstat_group = {
        .name  = "statistics",
        .attrs  = netstat_attrs,
 };
+
+#if IS_ENABLED(CONFIG_WIRELESS_EXT) || IS_ENABLED(CONFIG_CFG80211)
+static struct attribute *wireless_attrs[] = {
+       NULL
+};
+
+static struct attribute_group wireless_group = {
+       .name = "wireless",
+       .attrs = wireless_attrs,
+};
+#endif
 #endif /* CONFIG_SYSFS */
 
 #ifdef CONFIG_RPS
@@ -1409,6 +1420,15 @@ int netdev_register_kobject(struct net_device *net)
                groups++;
 
        *groups++ = &netstat_group;
+
+#if IS_ENABLED(CONFIG_WIRELESS_EXT) || IS_ENABLED(CONFIG_CFG80211)
+       if (net->ieee80211_ptr)
+               *groups++ = &wireless_group;
+#if IS_ENABLED(CONFIG_WIRELESS_EXT)
+       else if (net->wireless_handlers)
+               *groups++ = &wireless_group;
+#endif
+#endif
 #endif /* CONFIG_SYSFS */
 
        error = device_add(dev);
index 76d4c2c..fad649a 100644 (file)
@@ -2192,7 +2192,8 @@ static int nlmsg_populate_fdb(struct sk_buff *skb,
                        goto skip;
 
                err = nlmsg_populate_fdb_fill(skb, dev, ha->addr,
-                                             portid, seq, 0, NTF_SELF);
+                                             portid, seq,
+                                             RTM_NEWNEIGH, NTF_SELF);
                if (err < 0)
                        return err;
 skip:
index 6e04b1f..3f0636c 100644 (file)
@@ -3004,7 +3004,7 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
        skb_shinfo(nskb)->gso_size = pinfo->gso_size;
        pinfo->gso_size = 0;
        skb_header_release(p);
-       nskb->prev = p;
+       NAPI_GRO_CB(nskb)->last = p;
 
        nskb->data_len += p->len;
        nskb->truesize += p->truesize;
@@ -3030,8 +3030,8 @@ merge:
 
        __skb_pull(skb, offset);
 
-       p->prev->next = skb;
-       p->prev = skb;
+       NAPI_GRO_CB(p)->last->next = skb;
+       NAPI_GRO_CB(p)->last = skb;
        skb_header_release(skb);
 
 done:
@@ -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 f2eccd5..17ff9fd 100644 (file)
@@ -257,7 +257,8 @@ static inline bool icmpv4_xrlim_allow(struct net *net, struct rtable *rt,
                struct inet_peer *peer = inet_getpeer_v4(net->ipv4.peers, fl4->daddr, 1);
                rc = inet_peer_xrlim_allow(peer,
                                           net->ipv4.sysctl_icmp_ratelimit);
-               inet_putpeer(peer);
+               if (peer)
+                       inet_putpeer(peer);
        }
 out:
        return rc;
index 535584c..e23e16d 100644 (file)
@@ -44,6 +44,10 @@ struct inet_diag_entry {
        u16 dport;
        u16 family;
        u16 userlocks;
+#if IS_ENABLED(CONFIG_IPV6)
+       struct in6_addr saddr_storage;  /* for IPv4-mapped-IPv6 addresses */
+       struct in6_addr daddr_storage;  /* for IPv4-mapped-IPv6 addresses */
+#endif
 };
 
 static DEFINE_MUTEX(inet_diag_table_mutex);
@@ -428,25 +432,31 @@ static int inet_diag_bc_run(const struct nlattr *_bc,
                                break;
                        }
 
-                       if (cond->prefix_len == 0)
-                               break;
-
                        if (op->code == INET_DIAG_BC_S_COND)
                                addr = entry->saddr;
                        else
                                addr = entry->daddr;
 
+                       if (cond->family != AF_UNSPEC &&
+                           cond->family != entry->family) {
+                               if (entry->family == AF_INET6 &&
+                                   cond->family == AF_INET) {
+                                       if (addr[0] == 0 && addr[1] == 0 &&
+                                           addr[2] == htonl(0xffff) &&
+                                           bitstring_match(addr + 3,
+                                                           cond->addr,
+                                                           cond->prefix_len))
+                                               break;
+                               }
+                               yes = 0;
+                               break;
+                       }
+
+                       if (cond->prefix_len == 0)
+                               break;
                        if (bitstring_match(addr, cond->addr,
                                            cond->prefix_len))
                                break;
-                       if (entry->family == AF_INET6 &&
-                           cond->family == AF_INET) {
-                               if (addr[0] == 0 && addr[1] == 0 &&
-                                   addr[2] == htonl(0xffff) &&
-                                   bitstring_match(addr + 3, cond->addr,
-                                                   cond->prefix_len))
-                                       break;
-                       }
                        yes = 0;
                        break;
                }
@@ -509,6 +519,55 @@ static int valid_cc(const void *bc, int len, int cc)
        return 0;
 }
 
+/* Validate an inet_diag_hostcond. */
+static bool valid_hostcond(const struct inet_diag_bc_op *op, int len,
+                          int *min_len)
+{
+       int addr_len;
+       struct inet_diag_hostcond *cond;
+
+       /* Check hostcond space. */
+       *min_len += sizeof(struct inet_diag_hostcond);
+       if (len < *min_len)
+               return false;
+       cond = (struct inet_diag_hostcond *)(op + 1);
+
+       /* Check address family and address length. */
+       switch (cond->family) {
+       case AF_UNSPEC:
+               addr_len = 0;
+               break;
+       case AF_INET:
+               addr_len = sizeof(struct in_addr);
+               break;
+       case AF_INET6:
+               addr_len = sizeof(struct in6_addr);
+               break;
+       default:
+               return false;
+       }
+       *min_len += addr_len;
+       if (len < *min_len)
+               return false;
+
+       /* Check prefix length (in bits) vs address length (in bytes). */
+       if (cond->prefix_len > 8 * addr_len)
+               return false;
+
+       return true;
+}
+
+/* Validate a port comparison operator. */
+static inline bool valid_port_comparison(const struct inet_diag_bc_op *op,
+                                        int len, int *min_len)
+{
+       /* Port comparisons put the port in a follow-on inet_diag_bc_op. */
+       *min_len += sizeof(struct inet_diag_bc_op);
+       if (len < *min_len)
+               return false;
+       return true;
+}
+
 static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
 {
        const void *bc = bytecode;
@@ -516,29 +575,39 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
 
        while (len > 0) {
                const struct inet_diag_bc_op *op = bc;
+               int min_len = sizeof(struct inet_diag_bc_op);
 
 //printk("BC: %d %d %d {%d} / %d\n", op->code, op->yes, op->no, op[1].no, len);
                switch (op->code) {
-               case INET_DIAG_BC_AUTO:
                case INET_DIAG_BC_S_COND:
                case INET_DIAG_BC_D_COND:
+                       if (!valid_hostcond(bc, len, &min_len))
+                               return -EINVAL;
+                       break;
                case INET_DIAG_BC_S_GE:
                case INET_DIAG_BC_S_LE:
                case INET_DIAG_BC_D_GE:
                case INET_DIAG_BC_D_LE:
-               case INET_DIAG_BC_JMP:
-                       if (op->no < 4 || op->no > len + 4 || op->no & 3)
-                               return -EINVAL;
-                       if (op->no < len &&
-                           !valid_cc(bytecode, bytecode_len, len - op->no))
+                       if (!valid_port_comparison(bc, len, &min_len))
                                return -EINVAL;
                        break;
+               case INET_DIAG_BC_AUTO:
+               case INET_DIAG_BC_JMP:
                case INET_DIAG_BC_NOP:
                        break;
                default:
                        return -EINVAL;
                }
-               if (op->yes < 4 || op->yes > len + 4 || op->yes & 3)
+
+               if (op->code != INET_DIAG_BC_NOP) {
+                       if (op->no < min_len || op->no > len + 4 || op->no & 3)
+                               return -EINVAL;
+                       if (op->no < len &&
+                           !valid_cc(bytecode, bytecode_len, len - op->no))
+                               return -EINVAL;
+               }
+
+               if (op->yes < min_len || op->yes > len + 4 || op->yes & 3)
                        return -EINVAL;
                bc  += op->yes;
                len -= op->yes;
@@ -596,6 +665,36 @@ static int inet_twsk_diag_dump(struct inet_timewait_sock *tw,
                                   cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh);
 }
 
+/* Get the IPv4, IPv6, or IPv4-mapped-IPv6 local and remote addresses
+ * from a request_sock. For IPv4-mapped-IPv6 we must map IPv4 to IPv6.
+ */
+static inline void inet_diag_req_addrs(const struct sock *sk,
+                                      const struct request_sock *req,
+                                      struct inet_diag_entry *entry)
+{
+       struct inet_request_sock *ireq = inet_rsk(req);
+
+#if IS_ENABLED(CONFIG_IPV6)
+       if (sk->sk_family == AF_INET6) {
+               if (req->rsk_ops->family == AF_INET6) {
+                       entry->saddr = inet6_rsk(req)->loc_addr.s6_addr32;
+                       entry->daddr = inet6_rsk(req)->rmt_addr.s6_addr32;
+               } else if (req->rsk_ops->family == AF_INET) {
+                       ipv6_addr_set_v4mapped(ireq->loc_addr,
+                                              &entry->saddr_storage);
+                       ipv6_addr_set_v4mapped(ireq->rmt_addr,
+                                              &entry->daddr_storage);
+                       entry->saddr = entry->saddr_storage.s6_addr32;
+                       entry->daddr = entry->daddr_storage.s6_addr32;
+               }
+       } else
+#endif
+       {
+               entry->saddr = &ireq->loc_addr;
+               entry->daddr = &ireq->rmt_addr;
+       }
+}
+
 static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
                              struct request_sock *req,
                              struct user_namespace *user_ns,
@@ -637,8 +736,10 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
        r->idiag_inode = 0;
 #if IS_ENABLED(CONFIG_IPV6)
        if (r->idiag_family == AF_INET6) {
-               *(struct in6_addr *)r->id.idiag_src = inet6_rsk(req)->loc_addr;
-               *(struct in6_addr *)r->id.idiag_dst = inet6_rsk(req)->rmt_addr;
+               struct inet_diag_entry entry;
+               inet_diag_req_addrs(sk, req, &entry);
+               memcpy(r->id.idiag_src, entry.saddr, sizeof(struct in6_addr));
+               memcpy(r->id.idiag_dst, entry.daddr, sizeof(struct in6_addr));
        }
 #endif
 
@@ -691,18 +792,7 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk,
                                continue;
 
                        if (bc) {
-                               entry.saddr =
-#if IS_ENABLED(CONFIG_IPV6)
-                                       (entry.family == AF_INET6) ?
-                                       inet6_rsk(req)->loc_addr.s6_addr32 :
-#endif
-                                       &ireq->loc_addr;
-                               entry.daddr =
-#if IS_ENABLED(CONFIG_IPV6)
-                                       (entry.family == AF_INET6) ?
-                                       inet6_rsk(req)->rmt_addr.s6_addr32 :
-#endif
-                                       &ireq->rmt_addr;
+                               inet_diag_req_addrs(sk, req, &entry);
                                entry.dport = ntohs(ireq->rmt_port);
 
                                if (!inet_diag_bc_run(bc, &entry))
@@ -892,13 +982,16 @@ static int __inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
                struct inet_diag_req_v2 *r, struct nlattr *bc)
 {
        const struct inet_diag_handler *handler;
+       int err = 0;
 
        handler = inet_diag_lock_handler(r->sdiag_protocol);
        if (!IS_ERR(handler))
                handler->dump(skb, cb, r, bc);
+       else
+               err = PTR_ERR(handler);
        inet_diag_unlock_handler(handler);
 
-       return skb->len;
+       return err ? : skb->len;
 }
 
 static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
index 448e685..8d5cc75 100644 (file)
@@ -707,28 +707,27 @@ EXPORT_SYMBOL(ip_defrag);
 
 struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user)
 {
-       const struct iphdr *iph;
+       struct iphdr iph;
        u32 len;
 
        if (skb->protocol != htons(ETH_P_IP))
                return skb;
 
-       if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+       if (!skb_copy_bits(skb, 0, &iph, sizeof(iph)))
                return skb;
 
-       iph = ip_hdr(skb);
-       if (iph->ihl < 5 || iph->version != 4)
+       if (iph.ihl < 5 || iph.version != 4)
                return skb;
-       if (!pskb_may_pull(skb, iph->ihl*4))
-               return skb;
-       iph = ip_hdr(skb);
-       len = ntohs(iph->tot_len);
-       if (skb->len < len || len < (iph->ihl * 4))
+
+       len = ntohs(iph.tot_len);
+       if (skb->len < len || len < (iph.ihl * 4))
                return skb;
 
-       if (ip_is_fragment(ip_hdr(skb))) {
+       if (ip_is_fragment(&iph)) {
                skb = skb_share_check(skb, GFP_ATOMIC);
                if (skb) {
+                       if (!pskb_may_pull(skb, iph.ihl*4))
+                               return skb;
                        if (pskb_trim_rcsum(skb, len))
                                return skb;
                        memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
index 5eea4a8..14bbfcf 100644 (file)
@@ -457,19 +457,28 @@ static int do_ip_setsockopt(struct sock *sk, int level,
        struct inet_sock *inet = inet_sk(sk);
        int val = 0, err;
 
-       if (((1<<optname) & ((1<<IP_PKTINFO) | (1<<IP_RECVTTL) |
-                            (1<<IP_RECVOPTS) | (1<<IP_RECVTOS) |
-                            (1<<IP_RETOPTS) | (1<<IP_TOS) |
-                            (1<<IP_TTL) | (1<<IP_HDRINCL) |
-                            (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) |
-                            (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) |
-                            (1<<IP_PASSSEC) | (1<<IP_TRANSPARENT) |
-                            (1<<IP_MINTTL) | (1<<IP_NODEFRAG))) ||
-           optname == IP_UNICAST_IF ||
-           optname == IP_MULTICAST_TTL ||
-           optname == IP_MULTICAST_ALL ||
-           optname == IP_MULTICAST_LOOP ||
-           optname == IP_RECVORIGDSTADDR) {
+       switch (optname) {
+       case IP_PKTINFO:
+       case IP_RECVTTL:
+       case IP_RECVOPTS:
+       case IP_RECVTOS:
+       case IP_RETOPTS:
+       case IP_TOS:
+       case IP_TTL:
+       case IP_HDRINCL:
+       case IP_MTU_DISCOVER:
+       case IP_RECVERR:
+       case IP_ROUTER_ALERT:
+       case IP_FREEBIND:
+       case IP_PASSSEC:
+       case IP_TRANSPARENT:
+       case IP_MINTTL:
+       case IP_NODEFRAG:
+       case IP_UNICAST_IF:
+       case IP_MULTICAST_TTL:
+       case IP_MULTICAST_ALL:
+       case IP_MULTICAST_LOOP:
+       case IP_RECVORIGDSTADDR:
                if (optlen >= sizeof(int)) {
                        if (get_user(val, (int __user *) optval))
                                return -EFAULT;
index 1831092..858fddf 100644 (file)
@@ -338,12 +338,17 @@ static int vti_rcv(struct sk_buff *skb)
        if (tunnel != NULL) {
                struct pcpu_tstats *tstats;
 
+               if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
+                       return -1;
+
                tstats = this_cpu_ptr(tunnel->dev->tstats);
                u64_stats_update_begin(&tstats->syncp);
                tstats->rx_packets++;
                tstats->rx_bytes += skb->len;
                u64_stats_update_end(&tstats->syncp);
 
+               skb->mark = 0;
+               secpath_reset(skb);
                skb->dev = tunnel->dev;
                return 1;
        }
index 6168c4d..3eab2b2 100644 (file)
@@ -1318,6 +1318,10 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
                if (get_user(v, (u32 __user *)optval))
                        return -EFAULT;
 
+               /* "pimreg%u" should not exceed 16 bytes (IFNAMSIZ) */
+               if (v != RT_TABLE_DEFAULT && v >= 1000000000)
+                       return -EINVAL;
+
                rtnl_lock();
                ret = 0;
                if (sk == rtnl_dereference(mrt->mroute_sk)) {
index 9e0ffaf..a820472 100644 (file)
@@ -184,7 +184,8 @@ nf_nat_ipv4_out(unsigned int hooknum,
 
                if ((ct->tuplehash[dir].tuple.src.u3.ip !=
                     ct->tuplehash[!dir].tuple.dst.u3.ip) ||
-                   (ct->tuplehash[dir].tuple.src.u.all !=
+                   (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
+                    ct->tuplehash[dir].tuple.src.u.all !=
                     ct->tuplehash[!dir].tuple.dst.u.all))
                        if (nf_xfrm_me_harder(skb, AF_INET) < 0)
                                ret = NF_DROP;
@@ -221,6 +222,7 @@ nf_nat_ipv4_local_fn(unsigned int hooknum,
                }
 #ifdef CONFIG_XFRM
                else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
+                        ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
                         ct->tuplehash[dir].tuple.dst.u.all !=
                         ct->tuplehash[!dir].tuple.src.u.all)
                        if (nf_xfrm_me_harder(skb, AF_INET) < 0)
index 432f4bb..df25142 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);
@@ -1782,6 +1785,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
        if (dev_out->flags & IFF_LOOPBACK)
                flags |= RTCF_LOCAL;
 
+       do_cache = true;
        if (type == RTN_BROADCAST) {
                flags |= RTCF_BROADCAST | RTCF_LOCAL;
                fi = NULL;
@@ -1790,6 +1794,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
                if (!ip_check_mc_rcu(in_dev, fl4->daddr, fl4->saddr,
                                     fl4->flowi4_proto))
                        flags &= ~RTCF_LOCAL;
+               else
+                       do_cache = false;
                /* If multicast route do not exist use
                 * default one, but do not gateway in this case.
                 * Yes, it is hack.
@@ -1799,8 +1805,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
        }
 
        fnhe = NULL;
-       do_cache = fi != NULL;
-       if (fi) {
+       do_cache &= fi != NULL;
+       if (do_cache) {
                struct rtable __rcu **prth;
                struct fib_nh *nh = &FIB_RES_NH(*res);
 
@@ -2594,7 +2600,7 @@ int __init ip_rt_init(void)
                pr_err("Unable to create route proc files\n");
 #ifdef CONFIG_XFRM
        xfrm_init();
-       xfrm4_init(ip_rt_max_size);
+       xfrm4_init();
 #endif
        rtnl_register(PF_INET, RTM_GETROUTE, inet_rtm_getroute, NULL, NULL);
 
index f32c02e..e457c7a 100644 (file)
@@ -549,14 +549,12 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
                         !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);
@@ -832,8 +830,8 @@ static int tcp_send_mss(struct sock *sk, int *size_goal, int flags)
        return mss_now;
 }
 
-static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffset,
-                        size_t psize, int flags)
+static ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset,
+                               size_t size, int flags)
 {
        struct tcp_sock *tp = tcp_sk(sk);
        int mss_now, size_goal;
@@ -860,12 +858,9 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffse
        if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
                goto out_err;
 
-       while (psize > 0) {
+       while (size > 0) {
                struct sk_buff *skb = tcp_write_queue_tail(sk);
-               struct page *page = pages[poffset / PAGE_SIZE];
                int copy, i;
-               int offset = poffset % PAGE_SIZE;
-               int size = min_t(size_t, psize, PAGE_SIZE - offset);
                bool can_coalesce;
 
                if (!tcp_send_head(sk) || (copy = size_goal - skb->len) <= 0) {
@@ -914,8 +909,8 @@ new_segment:
                        TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_PSH;
 
                copied += copy;
-               poffset += copy;
-               if (!(psize -= copy))
+               offset += copy;
+               if (!(size -= copy))
                        goto out;
 
                if (skb->len < size_goal || (flags & MSG_OOB))
@@ -962,7 +957,7 @@ int tcp_sendpage(struct sock *sk, struct page *page, int offset,
                                        flags);
 
        lock_sock(sk);
-       res = do_tcp_sendpages(sk, &page, offset, size, flags);
+       res = do_tcp_sendpages(sk, page, offset, size, flags);
        release_sock(sk);
        return res;
 }
@@ -1214,7 +1209,7 @@ new_segment:
 wait_for_sndbuf:
                        set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
 wait_for_memory:
-                       if (copied && likely(!tp->repair))
+                       if (copied)
                                tcp_push(sk, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH);
 
                        if ((err = sk_stream_wait_memory(sk, &timeo)) != 0)
@@ -1225,7 +1220,7 @@ wait_for_memory:
        }
 
 out:
-       if (copied && likely(!tp->repair))
+       if (copied)
                tcp_push(sk, flags, mss_now, tp->nonagle);
        release_sock(sk);
        return copied + copied_syn;
@@ -2766,6 +2761,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 813b43a..834857f 100644 (file)
@@ -313,11 +313,13 @@ static void tcp_illinois_info(struct sock *sk, u32 ext,
                        .tcpv_rttcnt = ca->cnt_rtt,
                        .tcpv_minrtt = ca->base_rtt,
                };
-               u64 t = ca->sum_rtt;
 
-               do_div(t, ca->cnt_rtt);
-               info.tcpv_rtt = t;
+               if (info.tcpv_rttcnt > 0) {
+                       u64 t = ca->sum_rtt;
 
+                       do_div(t, info.tcpv_rttcnt);
+                       info.tcpv_rtt = t;
+               }
                nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info);
        }
 }
index 432c366..181fc82 100644 (file)
@@ -4529,6 +4529,9 @@ int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size)
        struct tcphdr *th;
        bool fragstolen;
 
+       if (size == 0)
+               return 0;
+
        skb = alloc_skb(size + sizeof(*th), sk->sk_allocation);
        if (!skb)
                goto err;
@@ -5310,11 +5313,6 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
                goto discard;
        }
 
-       /* ts_recent update must be made after we are sure that the packet
-        * is in window.
-        */
-       tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
-
        /* step 3: check security and precedence [ignored] */
 
        /* step 4: Check for a SYN
@@ -5549,6 +5547,11 @@ step5:
        if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0)
                goto discard;
 
+       /* ts_recent update must be made after we are sure that the packet
+        * is in window.
+        */
+       tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
+
        tcp_rcv_rtt_measure_ts(sk, skb);
 
        /* Process urgent data. */
@@ -5642,10 +5645,15 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
        tcp_fastopen_cache_set(sk, mss, cookie, syn_drop);
 
        if (data) { /* Retransmit unacked data in SYN */
-               tcp_retransmit_skb(sk, data);
+               tcp_for_write_queue_from(data, sk) {
+                       if (data == tcp_send_head(sk) ||
+                           __tcp_retransmit_skb(sk, data))
+                               break;
+               }
                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);
@@ -6118,6 +6134,11 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
        } else
                goto discard;
 
+       /* ts_recent update must be made after we are sure that the packet
+        * is in window.
+        */
+       tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
+
        /* step 6: check the URG bit */
        tcp_urg(sk, skb, th);
 
index ef998b0..0c4a643 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);
index 4c752a6..f696d7c 100644 (file)
@@ -1,7 +1,6 @@
 #include <linux/rcupdate.h>
 #include <linux/spinlock.h>
 #include <linux/jiffies.h>
-#include <linux/bootmem.h>
 #include <linux/module.h>
 #include <linux/cache.h>
 #include <linux/slab.h>
@@ -9,6 +8,7 @@
 #include <linux/tcp.h>
 #include <linux/hash.h>
 #include <linux/tcp_metrics.h>
+#include <linux/vmalloc.h>
 
 #include <net/inet_connection_sock.h>
 #include <net/net_namespace.h>
@@ -864,7 +864,7 @@ static int parse_nl_addr(struct genl_info *info, struct inetpeer_addr *addr,
        }
        a = info->attrs[TCP_METRICS_ATTR_ADDR_IPV6];
        if (a) {
-               if (nla_len(a) != sizeof(sizeof(struct in6_addr)))
+               if (nla_len(a) != sizeof(struct in6_addr))
                        return -EINVAL;
                addr->family = AF_INET6;
                memcpy(addr->addr.a6, nla_data(a), sizeof(addr->addr.a6));
@@ -1034,7 +1034,10 @@ static int __net_init tcp_net_metrics_init(struct net *net)
        net->ipv4.tcp_metrics_hash_log = order_base_2(slots);
        size = sizeof(struct tcpm_hash_bucket) << net->ipv4.tcp_metrics_hash_log;
 
-       net->ipv4.tcp_metrics_hash = kzalloc(size, GFP_KERNEL);
+       net->ipv4.tcp_metrics_hash = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
+       if (!net->ipv4.tcp_metrics_hash)
+               net->ipv4.tcp_metrics_hash = vzalloc(size);
+
        if (!net->ipv4.tcp_metrics_hash)
                return -ENOMEM;
 
@@ -1055,7 +1058,10 @@ static void __net_exit tcp_net_metrics_exit(struct net *net)
                        tm = next;
                }
        }
-       kfree(net->ipv4.tcp_metrics_hash);
+       if (is_vmalloc_addr(net->ipv4.tcp_metrics_hash))
+               vfree(net->ipv4.tcp_metrics_hash);
+       else
+               kfree(net->ipv4.tcp_metrics_hash);
 }
 
 static __net_initdata struct pernet_operations tcp_net_metrics_ops = {
index 27536ba..a7302d9 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 cfe6ffe..948ac27 100644 (file)
@@ -1986,6 +1986,9 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
                tso_segs = tcp_init_tso_segs(sk, skb, mss_now);
                BUG_ON(!tso_segs);
 
+               if (unlikely(tp->repair) && tp->repair_queue == TCP_SEND_QUEUE)
+                       goto repair; /* Skip network transmission */
+
                cwnd_quota = tcp_cwnd_test(tp, skb);
                if (!cwnd_quota)
                        break;
@@ -2026,6 +2029,7 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
                if (unlikely(tcp_transmit_skb(sk, skb, 1, gfp)))
                        break;
 
+repair:
                /* Advance the send_head.  This one is sent out.
                 * This call will increment packets_out.
                 */
@@ -2305,12 +2309,11 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *to,
  * state updates are done by the caller.  Returns non-zero if an
  * error occurred which prevented the send.
  */
-int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
+int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
 {
        struct tcp_sock *tp = tcp_sk(sk);
        struct inet_connection_sock *icsk = inet_csk(sk);
        unsigned int cur_mss;
-       int err;
 
        /* Inconslusive MTU probe */
        if (icsk->icsk_mtup.probe_size) {
@@ -2383,11 +2386,17 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
        if (unlikely(NET_IP_ALIGN && ((unsigned long)skb->data & 3))) {
                struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER,
                                                   GFP_ATOMIC);
-               err = nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) :
-                            -ENOBUFS;
+               return nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) :
+                             -ENOBUFS;
        } else {
-               err = tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC);
+               return tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC);
        }
+}
+
+int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
+{
+       struct tcp_sock *tp = tcp_sk(sk);
+       int err = __tcp_retransmit_skb(sk, skb);
 
        if (err == 0) {
                /* Update global TCP statistics. */
index fc04711..d47c1b4 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 05c5ab8..3be0ac2 100644 (file)
@@ -279,19 +279,8 @@ static void __exit xfrm4_policy_fini(void)
        xfrm_policy_unregister_afinfo(&xfrm4_policy_afinfo);
 }
 
-void __init xfrm4_init(int rt_max_size)
+void __init xfrm4_init(void)
 {
-       /*
-        * Select a default value for the gc_thresh based on the main route
-        * table hash size.  It seems to me the worst case scenario is when
-        * we have ipsec operating in transport mode, in which we create a
-        * dst_entry per socket.  The xfrm gc algorithm starts trying to remove
-        * entries at gc_thresh, and prevents new allocations as 2*gc_thresh
-        * so lets set an initial xfrm gc_thresh value at the rt_max_size/2.
-        * That will let us store an ipsec connection per route table entry,
-        * and start cleaning when were 1/2 full
-        */
-       xfrm4_dst_ops.gc_thresh = rt_max_size/2;
        dst_entries_init(&xfrm4_dst_ops);
 
        xfrm4_state_init();
index d7c56f8..0424e4e 100644 (file)
@@ -3064,14 +3064,15 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq, loff_t pos)
                struct hlist_node *n;
                hlist_for_each_entry_rcu_bh(ifa, n, &inet6_addr_lst[state->bucket],
                                         addr_lst) {
+                       if (!net_eq(dev_net(ifa->idev->dev), net))
+                               continue;
                        /* sync with offset */
                        if (p < state->offset) {
                                p++;
                                continue;
                        }
                        state->offset++;
-                       if (net_eq(dev_net(ifa->idev->dev), net))
-                               return ifa;
+                       return ifa;
                }
 
                /* prepare for next bucket */
@@ -3089,18 +3090,20 @@ static struct inet6_ifaddr *if6_get_next(struct seq_file *seq,
        struct hlist_node *n = &ifa->addr_lst;
 
        hlist_for_each_entry_continue_rcu_bh(ifa, n, addr_lst) {
+               if (!net_eq(dev_net(ifa->idev->dev), net))
+                       continue;
                state->offset++;
-               if (net_eq(dev_net(ifa->idev->dev), net))
-                       return ifa;
+               return ifa;
        }
 
        while (++state->bucket < IN6_ADDR_HSIZE) {
                state->offset = 0;
                hlist_for_each_entry_rcu_bh(ifa, n,
                                     &inet6_addr_lst[state->bucket], addr_lst) {
+                       if (!net_eq(dev_net(ifa->idev->dev), net))
+                               continue;
                        state->offset++;
-                       if (net_eq(dev_net(ifa->idev->dev), net))
-                               return ifa;
+                       return ifa;
                }
        }
 
index c4f9341..3064785 100644 (file)
@@ -252,6 +252,7 @@ struct dst_entry *inet6_csk_update_pmtu(struct sock *sk, u32 mtu)
                return NULL;
        dst->ops->update_pmtu(dst, sk, NULL, mtu);
 
-       return inet6_csk_route_socket(sk, &fl6);
+       dst = inet6_csk_route_socket(sk, &fl6);
+       return IS_ERR(dst) ? NULL : dst;
 }
 EXPORT_SYMBOL_GPL(inet6_csk_update_pmtu);
index 0185679..d5cb3c4 100644 (file)
@@ -1633,9 +1633,9 @@ static size_t ip6gre_get_size(const struct net_device *dev)
                /* IFLA_GRE_OKEY */
                nla_total_size(4) +
                /* IFLA_GRE_LOCAL */
-               nla_total_size(4) +
+               nla_total_size(sizeof(struct in6_addr)) +
                /* IFLA_GRE_REMOTE */
-               nla_total_size(4) +
+               nla_total_size(sizeof(struct in6_addr)) +
                /* IFLA_GRE_TTL */
                nla_total_size(1) +
                /* IFLA_GRE_TOS */
@@ -1659,8 +1659,8 @@ static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev)
            nla_put_be16(skb, IFLA_GRE_OFLAGS, p->o_flags) ||
            nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
            nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
-           nla_put(skb, IFLA_GRE_LOCAL, sizeof(struct in6_addr), &p->raddr) ||
-           nla_put(skb, IFLA_GRE_REMOTE, sizeof(struct in6_addr), &p->laddr) ||
+           nla_put(skb, IFLA_GRE_LOCAL, sizeof(struct in6_addr), &p->laddr) ||
+           nla_put(skb, IFLA_GRE_REMOTE, sizeof(struct in6_addr), &p->raddr) ||
            nla_put_u8(skb, IFLA_GRE_TTL, p->hop_limit) ||
            /*nla_put_u8(skb, IFLA_GRE_TOS, t->priority) ||*/
            nla_put_u8(skb, IFLA_GRE_ENCAP_LIMIT, p->encap_limit) ||
index ba6d13d..e02faed 100644 (file)
@@ -827,6 +827,7 @@ pref_skip_coa:
                if (val < 0 || val > 255)
                        goto e_inval;
                np->min_hopcount = val;
+               retv = 0;
                break;
        case IPV6_DONTFRAG:
                np->dontfrag = valbool;
index ff36194..2edce30 100644 (file)
@@ -535,7 +535,7 @@ static void ndisc_send_unsol_na(struct net_device *dev)
 {
        struct inet6_dev *idev;
        struct inet6_ifaddr *ifa;
-       struct in6_addr mcaddr;
+       struct in6_addr mcaddr = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
 
        idev = in6_dev_get(dev);
        if (!idev)
@@ -543,7 +543,6 @@ static void ndisc_send_unsol_na(struct net_device *dev)
 
        read_lock_bh(&idev->lock);
        list_for_each_entry(ifa, &idev->addr_list, if_list) {
-               addrconf_addr_solict_mult(&ifa->addr, &mcaddr);
                ndisc_send_na(dev, NULL, &mcaddr, &ifa->addr,
                              /*router=*/ !!idev->cnf.forwarding,
                              /*solicited=*/ false, /*override=*/ true,
index e418bd6..d57dab1 100644 (file)
@@ -186,7 +186,8 @@ nf_nat_ipv6_out(unsigned int hooknum,
 
                if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,
                                      &ct->tuplehash[!dir].tuple.dst.u3) ||
-                   (ct->tuplehash[dir].tuple.src.u.all !=
+                   (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
+                    ct->tuplehash[dir].tuple.src.u.all !=
                     ct->tuplehash[!dir].tuple.dst.u.all))
                        if (nf_xfrm_me_harder(skb, AF_INET6) < 0)
                                ret = NF_DROP;
@@ -222,6 +223,7 @@ nf_nat_ipv6_local_fn(unsigned int hooknum,
                }
 #ifdef CONFIG_XFRM
                else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
+                        ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
                         ct->tuplehash[dir].tuple.dst.u.all !=
                         ct->tuplehash[!dir].tuple.src.u.all)
                        if (nf_xfrm_me_harder(skb, AF_INET6))
index 18bd9bb..22c8ea9 100644 (file)
@@ -85,7 +85,7 @@ static struct ctl_table nf_ct_frag6_sysctl_table[] = {
        { }
 };
 
-static int __net_init nf_ct_frag6_sysctl_register(struct net *net)
+static int nf_ct_frag6_sysctl_register(struct net *net)
 {
        struct ctl_table *table;
        struct ctl_table_header *hdr;
@@ -127,7 +127,7 @@ static void __net_exit nf_ct_frags6_sysctl_unregister(struct net *net)
 }
 
 #else
-static int __net_init nf_ct_frag6_sysctl_register(struct net *net)
+static int nf_ct_frag6_sysctl_register(struct net *net)
 {
        return 0;
 }
index 7c7e963..b1e6cf0 100644 (file)
@@ -219,7 +219,7 @@ static struct dst_ops ip6_dst_blackhole_ops = {
 };
 
 static const u32 ip6_template_metrics[RTAX_MAX] = {
-       [RTAX_HOPLIMIT - 1] = 255,
+       [RTAX_HOPLIMIT - 1] = 0,
 };
 
 static const struct rt6_info ip6_null_entry_template = {
@@ -1232,7 +1232,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
        rt->rt6i_dst.addr = fl6->daddr;
        rt->rt6i_dst.plen = 128;
        rt->rt6i_idev     = idev;
-       dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255);
+       dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 0);
 
        spin_lock_bh(&icmp6_dst_lock);
        rt->dst.next = icmp6_dst_gc_list;
index 95a3a7a..496ce2c 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 1002e33..ae43c62 100644 (file)
@@ -441,6 +441,7 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify)
        lsap = irlmp_open_lsap(stsap_sel, &ttp_notify, 0);
        if (lsap == NULL) {
                IRDA_DEBUG(0, "%s: unable to allocate LSAP!!\n", __func__);
+               __irttp_close_tsap(self);
                return NULL;
        }
 
index 37b8b8b..76125c5 100644 (file)
@@ -291,6 +291,7 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p
 
 out_del_dev:
        free_netdev(dev);
+       spriv->dev = NULL;
 out_del_session:
        l2tp_session_delete(session);
 out:
index 05f3a31..7371f67 100644 (file)
@@ -2594,6 +2594,9 @@ static void ieee80211_mgmt_frame_register(struct wiphy *wiphy,
                else
                        local->probe_req_reg--;
 
+               if (!local->open_count)
+                       break;
+
                ieee80211_queue_work(&local->hw, &local->reconfig_filter);
                break;
        default:
index 5f3620f..c21e33d 100644 (file)
@@ -1108,7 +1108,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
        sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;
        sdata->u.ibss.ibss_join_req = jiffies;
 
-       memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN);
+       memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len);
        sdata->u.ibss.ssid_len = params->ssid_len;
 
        mutex_unlock(&sdata->u.ibss.mtx);
@@ -1151,10 +1151,6 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
 
        mutex_lock(&sdata->u.ibss.mtx);
 
-       sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;
-       memset(sdata->u.ibss.bssid, 0, ETH_ALEN);
-       sdata->u.ibss.ssid_len = 0;
-
        active_ibss = ieee80211_sta_active_ibss(sdata);
 
        if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) {
@@ -1175,6 +1171,10 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
                }
        }
 
+       ifibss->state = IEEE80211_IBSS_MLME_SEARCH;
+       memset(ifibss->bssid, 0, ETH_ALEN);
+       ifibss->ssid_len = 0;
+
        sta_info_flush(sdata->local, sdata);
 
        spin_lock_bh(&ifibss->incomplete_lock);
index 8c80455..156e583 100644 (file)
@@ -1314,6 +1314,8 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
                                         struct net_device *dev);
 netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                                       struct net_device *dev);
+void ieee80211_purge_tx_queue(struct ieee80211_hw *hw,
+                             struct sk_buff_head *skbs);
 
 /* HT */
 void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
index 6f8a73c..7de7717 100644 (file)
@@ -853,7 +853,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);
                        }
                }
        }
index c80c449..f57f597 100644 (file)
@@ -871,8 +871,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
                                local->hw.wiphy->cipher_suites,
                                sizeof(u32) * local->hw.wiphy->n_cipher_suites,
                                GFP_KERNEL);
-                       if (!suites)
-                               return -ENOMEM;
+                       if (!suites) {
+                               result = -ENOMEM;
+                               goto fail_wiphy_register;
+                       }
                        for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) {
                                u32 suite = local->hw.wiphy->cipher_suites[r];
                                if (suite == WLAN_CIPHER_SUITE_WEP40 ||
index e714ed8..1b7eed2 100644 (file)
@@ -3099,22 +3099,32 @@ 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) {
-               channel_type = NL80211_CHAN_HT20;
+       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.
+                */
 
-               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;
                }
        }
 
@@ -3549,6 +3559,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 +3576,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 83608ac..2c84185 100644 (file)
@@ -458,8 +458,6 @@ void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata)
                list_move_tail(&roc->list, &tmp_list);
                roc->abort = true;
        }
-
-       ieee80211_start_next_roc(local);
        mutex_unlock(&local->mtx);
 
        list_for_each_entry_safe(roc, tmp, &tmp_list, list) {
index 61c621e..00ade7f 100644 (file)
@@ -531,6 +531,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
 
                if (ieee80211_is_action(hdr->frame_control)) {
                        u8 category;
+
+                       /* make sure category field is present */
+                       if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE)
+                               return RX_DROP_MONITOR;
+
                        mgmt = (struct ieee80211_mgmt *)hdr;
                        category = mgmt->u.action.category;
                        if (category != WLAN_CATEGORY_MESH_ACTION &&
@@ -883,14 +888,16 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
                 */
                if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
                    ieee80211_is_data_present(hdr->frame_control)) {
-                       u16 ethertype;
-                       u8 *payload;
-
-                       payload = rx->skb->data +
-                               ieee80211_hdrlen(hdr->frame_control);
-                       ethertype = (payload[6] << 8) | payload[7];
-                       if (cpu_to_be16(ethertype) ==
-                           rx->sdata->control_port_protocol)
+                       unsigned int hdrlen;
+                       __be16 ethertype;
+
+                       hdrlen = ieee80211_hdrlen(hdr->frame_control);
+
+                       if (rx->skb->len < hdrlen + 8)
+                               return RX_DROP_MONITOR;
+
+                       skb_copy_bits(rx->skb, hdrlen + 6, &ethertype, 2);
+                       if (ethertype == rx->sdata->control_port_protocol)
                                return RX_CONTINUE;
                }
 
@@ -1462,11 +1469,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
 
        hdr = (struct ieee80211_hdr *)rx->skb->data;
        fc = hdr->frame_control;
+
+       if (ieee80211_is_ctl(fc))
+               return RX_CONTINUE;
+
        sc = le16_to_cpu(hdr->seq_ctrl);
        frag = sc & IEEE80211_SCTL_FRAG;
 
        if (likely((!ieee80211_has_morefrags(fc) && frag == 0) ||
-                  (rx->skb)->len < 24 ||
                   is_multicast_ether_addr(hdr->addr1))) {
                /* not fragmented */
                goto out;
@@ -1889,6 +1899,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
 
        hdr = (struct ieee80211_hdr *) skb->data;
        hdrlen = ieee80211_hdrlen(hdr->frame_control);
+
+       /* make sure fixed part of mesh header is there, also checks skb len */
+       if (!pskb_may_pull(rx->skb, hdrlen + 6))
+               return RX_DROP_MONITOR;
+
+       mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
+
+       /* make sure full mesh header is there, also checks skb len */
+       if (!pskb_may_pull(rx->skb,
+                          hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr)))
+               return RX_DROP_MONITOR;
+
+       /* reload pointers */
+       hdr = (struct ieee80211_hdr *) skb->data;
        mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
 
        /* frame is in RMC, don't forward */
@@ -1897,7 +1921,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
            mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata))
                return RX_DROP_MONITOR;
 
-       if (!ieee80211_is_data(hdr->frame_control))
+       if (!ieee80211_is_data(hdr->frame_control) ||
+           !(status->rx_flags & IEEE80211_RX_RA_MATCH))
                return RX_CONTINUE;
 
        if (!mesh_hdr->ttl)
@@ -1911,9 +1936,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
                if (is_multicast_ether_addr(hdr->addr1)) {
                        mpp_addr = hdr->addr3;
                        proxied_addr = mesh_hdr->eaddr1;
-               } else {
+               } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) {
+                       /* has_a4 already checked in ieee80211_rx_mesh_check */
                        mpp_addr = hdr->addr4;
                        proxied_addr = mesh_hdr->eaddr2;
+               } else {
+                       return RX_DROP_MONITOR;
                }
 
                rcu_read_lock();
@@ -1941,12 +1969,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
        }
        skb_set_queue_mapping(skb, q);
 
-       if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
-               goto out;
-
        if (!--mesh_hdr->ttl) {
                IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl);
-               return RX_DROP_MONITOR;
+               goto out;
        }
 
        if (!ifmsh->mshcfg.dot11MeshForwarding)
@@ -2353,6 +2378,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
                }
                break;
        case WLAN_CATEGORY_SELF_PROTECTED:
+               if (len < (IEEE80211_MIN_ACTION_SIZE +
+                          sizeof(mgmt->u.action.u.self_prot.action_code)))
+                       break;
+
                switch (mgmt->u.action.u.self_prot.action_code) {
                case WLAN_SP_MESH_PEERING_OPEN:
                case WLAN_SP_MESH_PEERING_CLOSE:
@@ -2371,6 +2400,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
                }
                break;
        case WLAN_CATEGORY_MESH_ACTION:
+               if (len < (IEEE80211_MIN_ACTION_SIZE +
+                          sizeof(mgmt->u.action.u.mesh_action.action_code)))
+                       break;
+
                if (!ieee80211_vif_is_mesh(&sdata->vif))
                        break;
                if (mesh_action_is_path_sel(mgmt) &&
@@ -2913,10 +2946,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
        if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
                local->dot11ReceivedFragmentCount++;
 
-       if (ieee80211_is_mgmt(fc))
-               err = skb_linearize(skb);
-       else
+       if (ieee80211_is_mgmt(fc)) {
+               /* drop frame if too short for header */
+               if (skb->len < ieee80211_hdrlen(fc))
+                       err = -ENOBUFS;
+               else
+                       err = skb_linearize(skb);
+       } else {
                err = !pskb_may_pull(skb, ieee80211_hdrlen(fc));
+       }
 
        if (err) {
                dev_kfree_skb(skb);
index c4cdbde..43e60b5 100644 (file)
@@ -917,7 +917,7 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
                                       struct cfg80211_sched_scan_request *req)
 {
        struct ieee80211_local *local = sdata->local;
-       struct ieee80211_sched_scan_ies sched_scan_ies;
+       struct ieee80211_sched_scan_ies sched_scan_ies = {};
        int ret, i;
 
        mutex_lock(&local->mtx);
index 797dd36..d2eb64e 100644 (file)
@@ -117,8 +117,8 @@ static void free_sta_work(struct work_struct *wk)
 
        for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
                local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]);
-               __skb_queue_purge(&sta->ps_tx_buf[ac]);
-               __skb_queue_purge(&sta->tx_filtered[ac]);
+               ieee80211_purge_tx_queue(&local->hw, &sta->ps_tx_buf[ac]);
+               ieee80211_purge_tx_queue(&local->hw, &sta->tx_filtered[ac]);
        }
 
 #ifdef CONFIG_MAC80211_MESH
@@ -141,7 +141,7 @@ static void free_sta_work(struct work_struct *wk)
                tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]);
                if (!tid_tx)
                        continue;
-               __skb_queue_purge(&tid_tx->pending);
+               ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending);
                kfree(tid_tx);
        }
 
@@ -650,7 +650,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 +679,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);
        }
 
        /*
@@ -961,6 +961,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
        struct ieee80211_local *local = sdata->local;
        struct sk_buff_head pending;
        int filtered = 0, buffered = 0, ac;
+       unsigned long flags;
 
        clear_sta_flag(sta, WLAN_STA_SP);
 
@@ -976,12 +977,16 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
        for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
                int count = skb_queue_len(&pending), tmp;
 
+               spin_lock_irqsave(&sta->tx_filtered[ac].lock, flags);
                skb_queue_splice_tail_init(&sta->tx_filtered[ac], &pending);
+               spin_unlock_irqrestore(&sta->tx_filtered[ac].lock, flags);
                tmp = skb_queue_len(&pending);
                filtered += tmp - count;
                count = tmp;
 
+               spin_lock_irqsave(&sta->ps_tx_buf[ac].lock, flags);
                skb_queue_splice_tail_init(&sta->ps_tx_buf[ac], &pending);
+               spin_unlock_irqrestore(&sta->ps_tx_buf[ac].lock, flags);
                tmp = skb_queue_len(&pending);
                buffered += tmp - count;
        }
index 3af0cc4..101eb88 100644 (file)
@@ -668,3 +668,12 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb)
        dev_kfree_skb_any(skb);
 }
 EXPORT_SYMBOL(ieee80211_free_txskb);
+
+void ieee80211_purge_tx_queue(struct ieee80211_hw *hw,
+                             struct sk_buff_head *skbs)
+{
+       struct sk_buff *skb;
+
+       while ((skb = __skb_dequeue(skbs)))
+               ieee80211_free_txskb(hw, skb);
+}
index c9bf83f..b858ebe 100644 (file)
@@ -1358,7 +1358,7 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
                if (tx->skb)
                        ieee80211_free_txskb(&tx->local->hw, tx->skb);
                else
-                       __skb_queue_purge(&tx->skbs);
+                       ieee80211_purge_tx_queue(&tx->local->hw, &tx->skbs);
                return -1;
        } else if (unlikely(res == TX_QUEUED)) {
                I802_DEBUG_INC(tx->local->tx_handlers_queued);
@@ -2120,10 +2120,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
  */
 void ieee80211_clear_tx_pending(struct ieee80211_local *local)
 {
+       struct sk_buff *skb;
        int i;
 
-       for (i = 0; i < local->hw.queues; i++)
-               skb_queue_purge(&local->pending[i]);
+       for (i = 0; i < local->hw.queues; i++) {
+               while ((skb = skb_dequeue(&local->pending[i])) != NULL)
+                       ieee80211_free_txskb(&local->hw, skb);
+       }
 }
 
 /*
index 22ca350..0151ae3 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;
                }
 
@@ -643,13 +643,41 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
                        break;
                }
 
-               if (id != WLAN_EID_VENDOR_SPECIFIC &&
-                   id != WLAN_EID_QUIET &&
-                   test_bit(id, seen_elems)) {
-                       elems->parse_error = true;
-                       left -= elen;
-                       pos += elen;
-                       continue;
+               switch (id) {
+               case WLAN_EID_SSID:
+               case WLAN_EID_SUPP_RATES:
+               case WLAN_EID_FH_PARAMS:
+               case WLAN_EID_DS_PARAMS:
+               case WLAN_EID_CF_PARAMS:
+               case WLAN_EID_TIM:
+               case WLAN_EID_IBSS_PARAMS:
+               case WLAN_EID_CHALLENGE:
+               case WLAN_EID_RSN:
+               case WLAN_EID_ERP_INFO:
+               case WLAN_EID_EXT_SUPP_RATES:
+               case WLAN_EID_HT_CAPABILITY:
+               case WLAN_EID_HT_OPERATION:
+               case WLAN_EID_VHT_CAPABILITY:
+               case WLAN_EID_VHT_OPERATION:
+               case WLAN_EID_MESH_ID:
+               case WLAN_EID_MESH_CONFIG:
+               case WLAN_EID_PEER_MGMT:
+               case WLAN_EID_PREQ:
+               case WLAN_EID_PREP:
+               case WLAN_EID_PERR:
+               case WLAN_EID_RANN:
+               case WLAN_EID_CHANNEL_SWITCH:
+               case WLAN_EID_EXT_CHANSWITCH_ANN:
+               case WLAN_EID_COUNTRY:
+               case WLAN_EID_PWR_CONSTRAINT:
+               case WLAN_EID_TIMEOUT_INTERVAL:
+                       if (test_bit(id, seen_elems)) {
+                               elems->parse_error = true;
+                               left -= elen;
+                               pos += elen;
+                               continue;
+                       }
+                       break;
                }
 
                if (calc_crc && id < 64 && (filter & (1ULL << id)))
@@ -1463,6 +1491,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                list_for_each_entry(sdata, &local->interfaces, list) {
                        if (sdata->vif.type != NL80211_IFTYPE_STATION)
                                continue;
+                       if (!sdata->u.mgd.associated)
+                               continue;
 
                        ieee80211_send_nullfunc(local, sdata, 0);
                }
index bdb53ab..8bd2f5c 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 ec3dba5..5c0b785 100644 (file)
@@ -173,6 +173,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
                return adtfn(set, &nip, timeout, flags);
        }
 
+       ip_to = ip;
        if (tb[IPSET_ATTR_IP_TO]) {
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
                if (ret)
@@ -185,8 +186,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
                if (!cidr || cidr > 32)
                        return -IPSET_ERR_INVALID_CIDR;
                ip_set_mask_from_to(ip, ip_to, cidr);
-       } else
-               ip_to = ip;
+       }
 
        hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
 
index 0171f75..6283351 100644 (file)
@@ -162,7 +162,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipport4_elem data = { };
-       u32 ip, ip_to = 0, p = 0, port, port_to;
+       u32 ip, ip_to, p = 0, port, port_to;
        u32 timeout = h->timeout;
        bool with_ports = false;
        int ret;
@@ -210,7 +210,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
                return ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
-       ip = ntohl(data.ip);
+       ip_to = ip = ntohl(data.ip);
        if (tb[IPSET_ATTR_IP_TO]) {
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
                if (ret)
@@ -223,8 +223,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
                if (!cidr || cidr > 32)
                        return -IPSET_ERR_INVALID_CIDR;
                ip_set_mask_from_to(ip, ip_to, cidr);
-       } else
-               ip_to = ip;
+       }
 
        port_to = port = ntohs(data.port);
        if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
index 6344ef5..6a21271 100644 (file)
@@ -166,7 +166,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipportip4_elem data = { };
-       u32 ip, ip_to = 0, p = 0, port, port_to;
+       u32 ip, ip_to, p = 0, port, port_to;
        u32 timeout = h->timeout;
        bool with_ports = false;
        int ret;
@@ -218,7 +218,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
                return ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
-       ip = ntohl(data.ip);
+       ip_to = ip = ntohl(data.ip);
        if (tb[IPSET_ATTR_IP_TO]) {
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
                if (ret)
@@ -231,8 +231,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
                if (!cidr || cidr > 32)
                        return -IPSET_ERR_INVALID_CIDR;
                ip_set_mask_from_to(ip, ip_to, cidr);
-       } else
-               ip_to = ip;
+       }
 
        port_to = port = ntohs(data.port);
        if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
index cb71f9a..2d5cd4e 100644 (file)
@@ -215,8 +215,8 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipportnet4_elem data = { .cidr = HOST_MASK - 1 };
-       u32 ip, ip_to = 0, p = 0, port, port_to;
-       u32 ip2_from = 0, ip2_to, ip2_last, ip2;
+       u32 ip, ip_to, p = 0, port, port_to;
+       u32 ip2_from, ip2_to, ip2_last, ip2;
        u32 timeout = h->timeout;
        bool with_ports = false;
        u8 cidr;
@@ -286,6 +286,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
                return ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
+       ip_to = ip;
        if (tb[IPSET_ATTR_IP_TO]) {
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
                if (ret)
@@ -306,6 +307,8 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
                if (port > port_to)
                        swap(port, port_to);
        }
+
+       ip2_to = ip2_from;
        if (tb[IPSET_ATTR_IP2_TO]) {
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to);
                if (ret)
index b9a6338..45a1014 100644 (file)
@@ -793,7 +793,7 @@ static struct ip_set_type hash_netiface_type __read_mostly = {
                [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
                [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
                [IPSET_ATTR_IFACE]      = { .type = NLA_NUL_STRING,
-                                           .len = IPSET_MAXNAMELEN - 1 },
+                                           .len  = IFNAMSIZ - 1 },
                [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
                [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
index 7e7198b..c4ee437 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 1b30b0d..962795e 100644 (file)
@@ -753,7 +753,8 @@ static int callforward_do_filter(const union nf_inet_addr *src,
                                   flowi4_to_flowi(&fl1), false)) {
                        if (!afinfo->route(&init_net, (struct dst_entry **)&rt2,
                                           flowi4_to_flowi(&fl2), false)) {
-                               if (rt1->rt_gateway == rt2->rt_gateway &&
+                               if (rt_nexthop(rt1, fl1.daddr) ==
+                                   rt_nexthop(rt2, fl2.daddr) &&
                                    rt1->dst.dev  == rt2->dst.dev)
                                        ret = 1;
                                dst_release(&rt2->dst);
index 8847b4d..701c88a 100644 (file)
@@ -41,7 +41,8 @@ MODULE_DESCRIPTION("cttimeout: Extended Netfilter Connection Tracking timeout tu
 static LIST_HEAD(cttimeout_list);
 
 static const struct nla_policy cttimeout_nla_policy[CTA_TIMEOUT_MAX+1] = {
-       [CTA_TIMEOUT_NAME]      = { .type = NLA_NUL_STRING },
+       [CTA_TIMEOUT_NAME]      = { .type = NLA_NUL_STRING,
+                                   .len  = CTNL_TIMEOUT_NAME_MAX - 1},
        [CTA_TIMEOUT_L3PROTO]   = { .type = NLA_U16 },
        [CTA_TIMEOUT_L4PROTO]   = { .type = NLA_U8 },
        [CTA_TIMEOUT_DATA]      = { .type = NLA_NESTED },
index 16c7125..ae7f5da 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 ee2e5bc..bd93e51 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 81aafa8..bea7464 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 01e944a..4da797f 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 cc10d07..9e8f4b2 100644 (file)
@@ -1210,7 +1210,7 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
        local->remote_miu = LLCP_DEFAULT_MIU;
        local->remote_lto = LLCP_DEFAULT_LTO;
 
-       list_add(&llcp_devices, &local->list);
+       list_add(&local->list, &llcp_devices);
 
        return 0;
 }
index 98c7063..733cbf4 100644 (file)
@@ -702,15 +702,11 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
                        /* We only match on the lower 8 bits of the opcode. */
                        if (ntohs(arp->ar_op) <= 0xff)
                                key->ip.proto = ntohs(arp->ar_op);
-
-                       if (key->ip.proto == ARPOP_REQUEST
-                                       || key->ip.proto == ARPOP_REPLY) {
-                               memcpy(&key->ipv4.addr.src, arp->ar_sip, sizeof(key->ipv4.addr.src));
-                               memcpy(&key->ipv4.addr.dst, arp->ar_tip, sizeof(key->ipv4.addr.dst));
-                               memcpy(key->ipv4.arp.sha, arp->ar_sha, ETH_ALEN);
-                               memcpy(key->ipv4.arp.tha, arp->ar_tha, ETH_ALEN);
-                               key_len = SW_FLOW_KEY_OFFSET(ipv4.arp);
-                       }
+                       memcpy(&key->ipv4.addr.src, arp->ar_sip, sizeof(key->ipv4.addr.src));
+                       memcpy(&key->ipv4.addr.dst, arp->ar_tip, sizeof(key->ipv4.addr.dst));
+                       memcpy(key->ipv4.arp.sha, arp->ar_sha, ETH_ALEN);
+                       memcpy(key->ipv4.arp.tha, arp->ar_tha, ETH_ALEN);
+                       key_len = SW_FLOW_KEY_OFFSET(ipv4.arp);
                }
        } else if (key->eth.type == htons(ETH_P_IPV6)) {
                int nh_len;             /* IPv6 Header + Extensions */
index 3c1e58b..a903348 100644 (file)
@@ -158,7 +158,7 @@ static int netdev_send(struct vport *vport, struct sk_buff *skb)
 
        if (unlikely(packet_length(skb) > mtu && !skb_is_gso(skb))) {
                net_warn_ratelimited("%s: dropped over-mtu packet: %d > %d\n",
-                                    ovs_dp_name(vport->dp),
+                                    netdev_vport->dev->name,
                                     packet_length(skb), mtu);
                goto error;
        }
index f0dd83c..9687fa1 100644 (file)
  * grp->index is the index of the group; and grp->slot_shift
  * is the shift for the corresponding (scaled) sigma_i.
  */
-#define QFQ_MAX_INDEX          19
-#define QFQ_MAX_WSHIFT         16
+#define QFQ_MAX_INDEX          24
+#define QFQ_MAX_WSHIFT         12
 
 #define        QFQ_MAX_WEIGHT          (1<<QFQ_MAX_WSHIFT)
-#define QFQ_MAX_WSUM           (2*QFQ_MAX_WEIGHT)
+#define QFQ_MAX_WSUM           (16*QFQ_MAX_WEIGHT)
 
 #define FRAC_BITS              30      /* fixed point arithmetic */
 #define ONE_FP                 (1UL << FRAC_BITS)
 #define IWSUM                  (ONE_FP/QFQ_MAX_WSUM)
 
-#define QFQ_MTU_SHIFT          11
+#define QFQ_MTU_SHIFT          16      /* to support TSO/GSO */
 #define QFQ_MIN_SLOT_SHIFT     (FRAC_BITS + QFQ_MTU_SHIFT - QFQ_MAX_INDEX)
+#define QFQ_MIN_LMAX           256     /* min possible lmax for a class */
 
 /*
  * Possible group states.  These values are used as indexes for the bitmaps
@@ -231,6 +232,32 @@ static void qfq_update_class_params(struct qfq_sched *q, struct qfq_class *cl,
        q->wsum += delta_w;
 }
 
+static void qfq_update_reactivate_class(struct qfq_sched *q,
+                                       struct qfq_class *cl,
+                                       u32 inv_w, u32 lmax, int delta_w)
+{
+       bool need_reactivation = false;
+       int i = qfq_calc_index(inv_w, lmax);
+
+       if (&q->groups[i] != cl->grp && cl->qdisc->q.qlen > 0) {
+               /*
+                * shift cl->F back, to not charge the
+                * class for the not-yet-served head
+                * packet
+                */
+               cl->F = cl->S;
+               /* remove class from its slot in the old group */
+               qfq_deactivate_class(q, cl);
+               need_reactivation = true;
+       }
+
+       qfq_update_class_params(q, cl, lmax, inv_w, delta_w);
+
+       if (need_reactivation) /* activate in new group */
+               qfq_activate_class(q, cl, qdisc_peek_len(cl->qdisc));
+}
+
+
 static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
                            struct nlattr **tca, unsigned long *arg)
 {
@@ -238,7 +265,7 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
        struct qfq_class *cl = (struct qfq_class *)*arg;
        struct nlattr *tb[TCA_QFQ_MAX + 1];
        u32 weight, lmax, inv_w;
-       int i, err;
+       int err;
        int delta_w;
 
        if (tca[TCA_OPTIONS] == NULL) {
@@ -270,16 +297,14 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
 
        if (tb[TCA_QFQ_LMAX]) {
                lmax = nla_get_u32(tb[TCA_QFQ_LMAX]);
-               if (!lmax || lmax > (1UL << QFQ_MTU_SHIFT)) {
+               if (lmax < QFQ_MIN_LMAX || lmax > (1UL << QFQ_MTU_SHIFT)) {
                        pr_notice("qfq: invalid max length %u\n", lmax);
                        return -EINVAL;
                }
        } else
-               lmax = 1UL << QFQ_MTU_SHIFT;
+               lmax = psched_mtu(qdisc_dev(sch));
 
        if (cl != NULL) {
-               bool need_reactivation = false;
-
                if (tca[TCA_RATE]) {
                        err = gen_replace_estimator(&cl->bstats, &cl->rate_est,
                                                    qdisc_root_sleeping_lock(sch),
@@ -291,24 +316,8 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
                if (lmax == cl->lmax && inv_w == cl->inv_w)
                        return 0; /* nothing to update */
 
-               i = qfq_calc_index(inv_w, lmax);
                sch_tree_lock(sch);
-               if (&q->groups[i] != cl->grp && cl->qdisc->q.qlen > 0) {
-                       /*
-                        * shift cl->F back, to not charge the
-                        * class for the not-yet-served head
-                        * packet
-                        */
-                       cl->F = cl->S;
-                       /* remove class from its slot in the old group */
-                       qfq_deactivate_class(q, cl);
-                       need_reactivation = true;
-               }
-
-               qfq_update_class_params(q, cl, lmax, inv_w, delta_w);
-
-               if (need_reactivation) /* activate in new group */
-                       qfq_activate_class(q, cl, qdisc_peek_len(cl->qdisc));
+               qfq_update_reactivate_class(q, cl, inv_w, lmax, delta_w);
                sch_tree_unlock(sch);
 
                return 0;
@@ -663,15 +672,48 @@ static void qfq_make_eligible(struct qfq_sched *q, u64 old_V)
 
 
 /*
- * XXX we should make sure that slot becomes less than 32.
- * This is guaranteed by the input values.
- * roundedS is always cl->S rounded on grp->slot_shift bits.
+ * If the weight and lmax (max_pkt_size) of the classes do not change,
+ * then QFQ guarantees that the slot index is never higher than
+ * 2 + ((1<<QFQ_MTU_SHIFT)/QFQ_MIN_LMAX) * (QFQ_MAX_WEIGHT/QFQ_MAX_WSUM).
+ *
+ * With the current values of the above constants, the index is
+ * then guaranteed to never be higher than 2 + 256 * (1 / 16) = 18.
+ *
+ * When the weight of a class is increased or the lmax of the class is
+ * decreased, a new class with smaller slot size may happen to be
+ * activated. The activation of this class should be properly delayed
+ * to when the service of the class has finished in the ideal system
+ * tracked by QFQ. If the activation of the class is not delayed to
+ * this reference time instant, then this class may be unjustly served
+ * before other classes waiting for service. This may cause
+ * (unfrequently) the above bound to the slot index to be violated for
+ * some of these unlucky classes.
+ *
+ * Instead of delaying the activation of the new class, which is quite
+ * complex, the following inaccurate but simple solution is used: if
+ * the slot index is higher than QFQ_MAX_SLOTS-2, then the timestamps
+ * of the class are shifted backward so as to let the slot index
+ * become equal to QFQ_MAX_SLOTS-2. This threshold is used because, if
+ * the slot index is above it, then the data structure implementing
+ * the bucket list either gets immediately corrupted or may get
+ * corrupted on a possible next packet arrival that causes the start
+ * time of the group to be shifted backward.
  */
 static void qfq_slot_insert(struct qfq_group *grp, struct qfq_class *cl,
                            u64 roundedS)
 {
        u64 slot = (roundedS - grp->S) >> grp->slot_shift;
-       unsigned int i = (grp->front + slot) % QFQ_MAX_SLOTS;
+       unsigned int i; /* slot index in the bucket list */
+
+       if (unlikely(slot > QFQ_MAX_SLOTS - 2)) {
+               u64 deltaS = roundedS - grp->S -
+                       ((u64)(QFQ_MAX_SLOTS - 2)<<grp->slot_shift);
+               cl->S -= deltaS;
+               cl->F -= deltaS;
+               slot = QFQ_MAX_SLOTS - 2;
+       }
+
+       i = (grp->front + slot) % QFQ_MAX_SLOTS;
 
        hlist_add_head(&cl->next, &grp->slots[i]);
        __set_bit(slot, &grp->full_slots);
@@ -892,6 +934,13 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        }
        pr_debug("qfq_enqueue: cl = %x\n", cl->common.classid);
 
+       if (unlikely(cl->lmax < qdisc_pkt_len(skb))) {
+               pr_debug("qfq: increasing maxpkt from %u to %u for class %u",
+                         cl->lmax, qdisc_pkt_len(skb), cl->common.classid);
+               qfq_update_reactivate_class(q, cl, cl->inv_w,
+                                           qdisc_pkt_len(skb), 0);
+       }
+
        err = qdisc_enqueue(skb, cl->qdisc);
        if (unlikely(err != NET_XMIT_SUCCESS)) {
                pr_debug("qfq_enqueue: enqueue failed %d\n", err);
index 7c2df9c..69ce21e 100644 (file)
@@ -183,7 +183,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
 
        msg = sctp_datamsg_new(GFP_KERNEL);
        if (!msg)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        /* Note: Calculate this outside of the loop, so that all fragments
         * have the same expiration.
@@ -280,11 +280,14 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
 
                chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0);
 
-               if (!chunk)
+               if (!chunk) {
+                       err = -ENOMEM;
                        goto errout;
+               }
+
                err = sctp_user_addto_chunk(chunk, offset, len, msgh->msg_iov);
                if (err < 0)
-                       goto errout;
+                       goto errout_chunk_free;
 
                offset += len;
 
@@ -315,8 +318,10 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
 
                chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0);
 
-               if (!chunk)
+               if (!chunk) {
+                       err = -ENOMEM;
                        goto errout;
+               }
 
                err = sctp_user_addto_chunk(chunk, offset, over,msgh->msg_iov);
 
@@ -324,7 +329,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
                __skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr
                           - (__u8 *)chunk->skb->data);
                if (err < 0)
-                       goto errout;
+                       goto errout_chunk_free;
 
                sctp_datamsg_assign(msg, chunk);
                list_add_tail(&chunk->frag_list, &msg->chunks);
@@ -332,6 +337,9 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
 
        return msg;
 
+errout_chunk_free:
+       sctp_chunk_free(chunk);
+
 errout:
        list_for_each_safe(pos, temp, &msg->chunks) {
                list_del_init(pos);
@@ -339,7 +347,7 @@ errout:
                sctp_chunk_free(chunk);
        }
        sctp_datamsg_put(msg);
-       return NULL;
+       return ERR_PTR(err);
 }
 
 /* Check whether this message has expired. */
index c3bea26..9966e7b 100644 (file)
@@ -102,7 +102,7 @@ static const struct file_operations sctp_snmp_seq_fops = {
        .open    = sctp_snmp_seq_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
-       .release = single_release,
+       .release = single_release_net,
 };
 
 /* Set up the proc fs entry for 'snmp' object. */
@@ -251,7 +251,7 @@ static const struct file_operations sctp_eps_seq_fops = {
        .open    = sctp_eps_seq_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
-       .release = seq_release,
+       .release = seq_release_net,
 };
 
 /* Set up the proc fs entry for 'eps' object. */
@@ -372,7 +372,7 @@ static const struct file_operations sctp_assocs_seq_fops = {
        .open    = sctp_assocs_seq_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
-       .release = seq_release,
+       .release = seq_release_net,
 };
 
 /* Set up the proc fs entry for 'assocs' object. */
@@ -517,7 +517,7 @@ static const struct file_operations sctp_remaddr_seq_fops = {
        .open = sctp_remaddr_seq_open,
        .read = seq_read,
        .llseek = seq_lseek,
-       .release = seq_release,
+       .release = seq_release_net,
 };
 
 int __net_init sctp_remaddr_proc_init(struct net *net)
index 57f7de8..6773d78 100644 (file)
@@ -1642,8 +1642,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                                        asoc->outqueue.outstanding_bytes;
                        sackh.num_gap_ack_blocks = 0;
                        sackh.num_dup_tsns = 0;
+                       chunk->subh.sack_hdr = &sackh;
                        sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK,
-                                       SCTP_SACKH(&sackh));
+                                       SCTP_CHUNK(chunk));
                        break;
 
                case SCTP_CMD_DISCARD_PACKET:
index 59d16ea..406d957 100644 (file)
@@ -974,7 +974,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk,
        void *addr_buf;
        struct sctp_af *af;
 
-       SCTP_DEBUG_PRINTK("sctp_setsocktopt_bindx: sk %p addrs %p"
+       SCTP_DEBUG_PRINTK("sctp_setsockopt_bindx: sk %p addrs %p"
                          " addrs_size %d opt %d\n", sk, addrs, addrs_size, op);
 
        if (unlikely(addrs_size <= 0))
@@ -1915,8 +1915,8 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
 
        /* Break the message into multiple chunks of maximum size. */
        datamsg = sctp_datamsg_from_user(asoc, sinfo, msg, msg_len);
-       if (!datamsg) {
-               err = -ENOMEM;
+       if (IS_ERR(datamsg)) {
+               err = PTR_ERR(datamsg);
                goto out_free;
        }
 
index 953c21e..206cf52 100644 (file)
@@ -331,7 +331,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt)
                 * 1/8, rto_alpha would be expressed as 3.
                 */
                tp->rttvar = tp->rttvar - (tp->rttvar >> net->sctp.rto_beta)
-                       + ((abs(tp->srtt - rtt)) >> net->sctp.rto_beta);
+                       + (((__u32)abs64((__s64)tp->srtt - (__s64)rtt)) >> net->sctp.rto_beta);
                tp->srtt = tp->srtt - (tp->srtt >> net->sctp.rto_alpha)
                        + (rtt >> net->sctp.rto_alpha);
        } else {
index 5a3d675..a9c0bbc 100644 (file)
@@ -172,7 +172,7 @@ out_free:
                xprt_free_allocation(req);
 
        dprintk("RPC:       setup backchannel transport failed\n");
-       return -1;
+       return -ENOMEM;
 }
 EXPORT_SYMBOL_GPL(xprt_setup_backchannel);
 
index 2a68bb3..fc2f7aa 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 aaaadfb..75853ca 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 111ff83..b36f0fc 100644 (file)
@@ -116,7 +116,6 @@ void tipc_handler_stop(void)
                return;
 
        handler_enabled = 0;
-       tasklet_disable(&tipc_tasklet);
        tasklet_kill(&tipc_tasklet);
 
        spin_lock_bh(&qitem_lock);
index 443d4d7..3f72530 100644 (file)
@@ -526,8 +526,7 @@ int wiphy_register(struct wiphy *wiphy)
                for (i = 0; i < sband->n_channels; i++) {
                        sband->channels[i].orig_flags =
                                sband->channels[i].flags;
-                       sband->channels[i].orig_mag =
-                               sband->channels[i].max_antenna_gain;
+                       sband->channels[i].orig_mag = INT_MAX;
                        sband->channels[i].orig_mpwr =
                                sband->channels[i].max_power;
                        sband->channels[i].band = band;
index 8016fee..904a7f3 100644 (file)
@@ -457,20 +457,14 @@ 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);
 }
index 3b8cbbc..b75756b 100644 (file)
@@ -141,9 +141,8 @@ static const struct ieee80211_regdomain world_regdom = {
        .reg_rules = {
                /* IEEE 802.11b/g, channels 1..11 */
                REG_RULE(2412-10, 2462+10, 40, 6, 20, 0),
-               /* IEEE 802.11b/g, channels 12..13. No HT40
-                * channel fits here. */
-               REG_RULE(2467-10, 2472+10, 20, 6, 20,
+               /* IEEE 802.11b/g, channels 12..13. */
+               REG_RULE(2467-10, 2472+10, 40, 6, 20,
                        NL80211_RRF_PASSIVE_SCAN |
                        NL80211_RRF_NO_IBSS),
                /* IEEE 802.11 channel 14 - Only JP enables
@@ -908,7 +907,7 @@ static void handle_channel(struct wiphy *wiphy,
                        map_regdom_flags(reg_rule->flags) | bw_flags;
                chan->max_antenna_gain = chan->orig_mag =
                        (int) MBI_TO_DBI(power_rule->max_antenna_gain);
-               chan->max_power = chan->orig_mpwr =
+               chan->max_reg_power = chan->max_power = chan->orig_mpwr =
                        (int) MBM_TO_DBM(power_rule->max_eirp);
                return;
        }
@@ -1331,7 +1330,8 @@ static void handle_channel_custom(struct wiphy *wiphy,
 
        chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
        chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
-       chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp);
+       chan->max_reg_power = chan->max_power =
+               (int) MBM_TO_DBM(power_rule->max_eirp);
 }
 
 static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band,
index ef35f4e..2762e83 100644 (file)
@@ -309,23 +309,21 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)
 }
 EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
 
-static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
+unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
 {
        int ae = meshhdr->flags & MESH_FLAGS_AE;
-       /* 7.1.3.5a.2 */
+       /* 802.11-2012, 8.2.4.7.3 */
        switch (ae) {
+       default:
        case 0:
                return 6;
        case MESH_FLAGS_AE_A4:
                return 12;
        case MESH_FLAGS_AE_A5_A6:
                return 18;
-       case (MESH_FLAGS_AE_A4 | MESH_FLAGS_AE_A5_A6):
-               return 24;
-       default:
-               return 6;
        }
 }
+EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
 
 int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
                           enum nl80211_iftype iftype)
@@ -373,6 +371,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
                        /* make sure meshdr->flags is on the linear part */
                        if (!pskb_may_pull(skb, hdrlen + 1))
                                return -1;
+                       if (meshdr->flags & MESH_FLAGS_AE_A4)
+                               return -1;
                        if (meshdr->flags & MESH_FLAGS_AE_A5_A6) {
                                skb_copy_bits(skb, hdrlen +
                                        offsetof(struct ieee80211s_hdr, eaddr1),
@@ -397,6 +397,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
                        /* make sure meshdr->flags is on the linear part */
                        if (!pskb_may_pull(skb, hdrlen + 1))
                                return -1;
+                       if (meshdr->flags & MESH_FLAGS_AE_A5_A6)
+                               return -1;
                        if (meshdr->flags & MESH_FLAGS_AE_A4)
                                skb_copy_bits(skb, hdrlen +
                                        offsetof(struct ieee80211s_hdr, eaddr1),
index 40caf3c..d17e0ea 100644 (file)
@@ -5,7 +5,7 @@
 # and for each file listed in this file with generic-y creates
 # a small wrapper file in $(obj) (arch/$(SRCARCH)/include/generated/asm)
 
-kbuild-file := $(srctree)/arch/$(SRCARCH)/include/asm/Kbuild
+kbuild-file := $(srctree)/arch/$(SRCARCH)/include/$(src)/Kbuild
 -include $(kbuild-file)
 
 include scripts/Kbuild.include
index c3f69ae..4d908d1 100644 (file)
@@ -27,7 +27,7 @@ endif
 installed-mod-fw := $(addprefix $(INSTALL_FW_PATH)/,$(mod-fw))
 
 installed-fw := $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-all))
-installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/.
+installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/./
 
 # Workaround for make < 3.81, where .SECONDEXPANSION doesn't work.
 PHONY += $(INSTALL_FW_PATH)/$$(%) install-all-dirs
@@ -42,7 +42,7 @@ quiet_cmd_install = INSTALL $(subst $(srctree)/,,$@)
 $(installed-fw-dirs):
        $(call cmd,mkdir)
 
-$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $$(dir $(INSTALL_FW_PATH)/%)
+$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $(INSTALL_FW_PATH)/$$(dir %)
        $(call cmd,install)
 
 PHONY +=  __fw_install __fw_modinst FORCE
index 0be6f11..bdf42fd 100644 (file)
@@ -266,6 +266,9 @@ $(obj)/%.dtb.S: $(obj)/%.dtb
 quiet_cmd_dtc = DTC     $@
 cmd_dtc = $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 $(DTC_FLAGS) -d $(depfile) $<
 
+$(obj)/%.dtb: $(src)/%.dts FORCE
+       $(call if_changed_dep,dtc)
+
 # Bzip2
 # ---------------------------------------------------------------------------
 
index 3d13d3a..ecbb447 100644 (file)
@@ -16,8 +16,9 @@ PHONY += $(modules)
 __modinst: $(modules)
        @:
 
+# Don't stop modules_install if we can't sign external 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 $@) $(patsubst %,|| true,$(KBUILD_EXTMOD))
 
 # Modules built outside the kernel source tree go into extra by default
 INSTALL_MOD_DIR ?= extra
index 0020891..a1cb022 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 21a9f5d..f18750e 100755 (executable)
@@ -1890,8 +1890,10 @@ sub process {
                }
 
                if ($realfile =~ m@^(drivers/net/|net/)@ &&
-                   $rawline !~ m@^\+[ \t]*(\/\*|\*\/)@ &&
-                   $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) {
+                   $rawline !~ m@^\+[ \t]*\*/[ \t]*$@ &&       #trailing */
+                   $rawline !~ m@^\+.*/\*.*\*/[ \t]*$@ &&      #inline /*...*/
+                   $rawline !~ m@^\+.*\*{2,}/[ \t]*$@ &&       #trailing **/
+                   $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) {    #non blank */
                        WARN("NETWORKING_BLOCK_COMMENT_STYLE",
                             "networking block comments put the trailing */ on a separate line\n" . $herecurr);
                }
index 6d1c6bb..2a48022 100644 (file)
@@ -27,3 +27,5 @@ HOSTCFLAGS_dtc-parser.tab.o := $(HOSTCFLAGS_DTC)
 # dependencies on generated files need to be listed explicitly
 $(obj)/dtc-lexer.lex.o: $(obj)/dtc-parser.tab.h
 
+# generated files need to be cleaned explicitly
+clean-files    := dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h
index d501c86..3e42a07 100644 (file)
@@ -161,51 +161,27 @@ struct node {
        struct label *labels;
 };
 
-static inline struct label *for_each_label_next(struct label *l)
-{
-       do {
-               l = l->next;
-       } while (l && l->deleted);
-
-       return l;
-}
-
-#define for_each_label(l0, l) \
-       for ((l) = (l0); (l); (l) = for_each_label_next(l))
-
 #define for_each_label_withdel(l0, l) \
        for ((l) = (l0); (l); (l) = (l)->next)
 
-static inline struct property *for_each_property_next(struct property *p)
-{
-       do {
-               p = p->next;
-       } while (p && p->deleted);
-
-       return p;
-}
-
-#define for_each_property(n, p) \
-       for ((p) = (n)->proplist; (p); (p) = for_each_property_next(p))
+#define for_each_label(l0, l) \
+       for_each_label_withdel(l0, l) \
+               if (!(l)->deleted)
 
 #define for_each_property_withdel(n, p) \
        for ((p) = (n)->proplist; (p); (p) = (p)->next)
 
-static inline struct node *for_each_child_next(struct node *c)
-{
-       do {
-               c = c->next_sibling;
-       } while (c && c->deleted);
-
-       return c;
-}
-
-#define for_each_child(n, c) \
-       for ((c) = (n)->children; (c); (c) = for_each_child_next(c))
+#define for_each_property(n, p) \
+       for_each_property_withdel(n, p) \
+               if (!(p)->deleted)
 
 #define for_each_child_withdel(n, c) \
        for ((c) = (n)->children; (c); (c) = (c)->next_sibling)
 
+#define for_each_child(n, c) \
+       for_each_child_withdel(n, c) \
+               if (!(c)->deleted)
+
 void add_label(struct label **labels, char *label);
 void delete_labels(struct label **labels);
 
index 239d22d..6c353ae 100644 (file)
@@ -42,6 +42,9 @@ foreach my $filename (@files) {
                $line =~ s/(^|\s)(inline)\b/$1__$2__/g;
                $line =~ s/(^|\s)(asm)\b(\s|[(]|$)/$1__$2__$3/g;
                $line =~ s/(^|\s|[(])(volatile)\b(\s|[(]|$)/$1__$2__$3/g;
+               $line =~ s/#ifndef _UAPI/#ifndef /;
+               $line =~ s/#define _UAPI/#define /;
+               $line =~ s!#endif /[*] _UAPI!#endif /* !;
                printf {$out} "%s", $line;
        }
        close $out;
index bd2e098..cdd4860 100644 (file)
@@ -12,7 +12,7 @@ extern "C" {
 
 #include <assert.h>
 #include <stdio.h>
-#include <sys/queue.h>
+#include "list.h"
 #ifndef __cplusplus
 #include <stdbool.h>
 #endif
@@ -175,12 +175,11 @@ struct menu {
 #define MENU_ROOT              0x0002
 
 struct jump_key {
-       CIRCLEQ_ENTRY(jump_key) entries;
+       struct list_head entries;
        size_t offset;
        struct menu *target;
        int index;
 };
-CIRCLEQ_HEAD(jk_head, jump_key);
 
 #define JUMP_NB                        9
 
diff --git a/scripts/kconfig/list.h b/scripts/kconfig/list.h
new file mode 100644 (file)
index 0000000..0ae730b
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef LIST_H
+#define LIST_H
+
+/*
+ * Copied from include/linux/...
+ */
+
+#undef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+/**
+ * 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) );})
+
+
+struct list_head {
+       struct list_head *next, *prev;
+};
+
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+       struct list_head name = LIST_HEAD_INIT(name)
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr:       the &struct list_head pointer.
+ * @type:      the type of the struct this is embedded in.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+       container_of(ptr, type, member)
+
+/**
+ * list_for_each_entry -       iterate over list of given type
+ * @pos:       the type * to use as a loop cursor.
+ * @head:      the head for your list.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member)                         \
+       for (pos = list_entry((head)->next, typeof(*pos), member);      \
+            &pos->member != (head);    \
+            pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(const struct list_head *head)
+{
+       return head->next == head;
+}
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *_new,
+                             struct list_head *prev,
+                             struct list_head *next)
+{
+       next->prev = _new;
+       _new->next = next;
+       _new->prev = prev;
+       prev->next = _new;
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *_new, struct list_head *head)
+{
+       __list_add(_new, head->prev, head);
+}
+
+#endif
index 1d1c085..ef1a738 100644 (file)
@@ -21,9 +21,9 @@ P(menu_get_root_menu,struct menu *,(struct menu *menu));
 P(menu_get_parent_menu,struct menu *,(struct menu *menu));
 P(menu_has_help,bool,(struct menu *menu));
 P(menu_get_help,const char *,(struct menu *menu));
-P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct jk_head
+P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct list_head
                         *head));
-P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct jk_head
+P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct list_head
                                   *head));
 P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help));
 
index 48f6744..53975cf 100644 (file)
@@ -312,7 +312,7 @@ static void set_config_filename(const char *config_filename)
 
 
 struct search_data {
-       struct jk_head *head;
+       struct list_head *head;
        struct menu **targets;
        int *keys;
 };
@@ -323,7 +323,7 @@ static void update_text(char *buf, size_t start, size_t end, void *_data)
        struct jump_key *pos;
        int k = 0;
 
-       CIRCLEQ_FOREACH(pos, data->head, entries) {
+       list_for_each_entry(pos, data->head, entries) {
                if (pos->offset >= start && pos->offset < end) {
                        char header[4];
 
@@ -375,7 +375,7 @@ again:
 
        sym_arr = sym_re_search(dialog_input);
        do {
-               struct jk_head head = CIRCLEQ_HEAD_INITIALIZER(head);
+               LIST_HEAD(head);
                struct menu *targets[JUMP_NB];
                int keys[JUMP_NB + 1], i;
                struct search_data data = {
index a3cade6..e98a05c 100644 (file)
@@ -508,7 +508,7 @@ const char *menu_get_help(struct menu *menu)
 }
 
 static void get_prompt_str(struct gstr *r, struct property *prop,
-                          struct jk_head *head)
+                          struct list_head *head)
 {
        int i, j;
        struct menu *submenu[8], *menu, *location = NULL;
@@ -544,12 +544,13 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
                } else
                        jump->target = location;
 
-               if (CIRCLEQ_EMPTY(head))
+               if (list_empty(head))
                        jump->index = 0;
                else
-                       jump->index = CIRCLEQ_LAST(head)->index + 1;
+                       jump->index = list_entry(head->prev, struct jump_key,
+                                                entries)->index + 1;
 
-               CIRCLEQ_INSERT_TAIL(head, jump, entries);
+               list_add_tail(&jump->entries, head);
        }
 
        if (i > 0) {
@@ -573,7 +574,8 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
 /*
  * head is optional and may be NULL
  */
-void get_symbol_str(struct gstr *r, struct symbol *sym, struct jk_head *head)
+void get_symbol_str(struct gstr *r, struct symbol *sym,
+                   struct list_head *head)
 {
        bool hit;
        struct property *prop;
@@ -612,7 +614,7 @@ void get_symbol_str(struct gstr *r, struct symbol *sym, struct jk_head *head)
        str_append(r, "\n\n");
 }
 
-struct gstr get_relations_str(struct symbol **sym_arr, struct jk_head *head)
+struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head)
 {
        struct symbol *sym;
        struct gstr res = str_new();
old mode 100644 (file)
new mode 100755 (executable)
index e58e34e..974a20b
-#!/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 7b3021c..5706b74 100644 (file)
@@ -57,7 +57,7 @@ cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \
 
 $(obj)/capability.o : $(obj)/capability_names.h
 $(obj)/resource.o : $(obj)/rlim_names.h
-$(obj)/capability_names.h : $(srctree)/include/linux/capability.h \
+$(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
                            $(src)/Makefile
        $(call cmd,make-caps)
 $(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \
index cf5fd22..8132003 100644 (file)
@@ -724,6 +724,8 @@ fail:
  */
 static void free_profile(struct aa_profile *profile)
 {
+       struct aa_profile *p;
+
        AA_DEBUG("%s(%p)\n", __func__, profile);
 
        if (!profile)
@@ -751,7 +753,27 @@ static void free_profile(struct aa_profile *profile)
        aa_put_dfa(profile->xmatch);
        aa_put_dfa(profile->policy.dfa);
 
-       aa_put_profile(profile->replacedby);
+       /* put the profile reference for replacedby, but not via
+        * put_profile(kref_put).
+        * replacedby can form a long chain that can result in cascading
+        * frees that blows the stack because kref_put makes a nested fn
+        * call (it looks like recursion, with free_profile calling
+        * free_profile) for each profile in the chain lp#1056078.
+        */
+       for (p = profile->replacedby; p; ) {
+               if (atomic_dec_and_test(&p->base.count.refcount)) {
+                       /* no more refs on p, grab its replacedby */
+                       struct aa_profile *next = p->replacedby;
+                       /* break the chain */
+                       p->replacedby = NULL;
+                       /* now free p, chain is broken */
+                       free_profile(p);
+
+                       /* follow up with next profile in the chain */
+                       p = next;
+               } else
+                       break;
+       }
 
        kzfree(profile);
 }
index 44dfc41..b08d20c 100644 (file)
@@ -42,7 +42,10 @@ struct dev_exception_item {
 struct dev_cgroup {
        struct cgroup_subsys_state css;
        struct list_head exceptions;
-       bool deny_all;
+       enum {
+               DEVCG_DEFAULT_ALLOW,
+               DEVCG_DEFAULT_DENY,
+       } behavior;
 };
 
 static inline struct dev_cgroup *css_to_devcgroup(struct cgroup_subsys_state *s)
@@ -161,8 +164,8 @@ static void dev_exception_clean(struct dev_cgroup *dev_cgroup)
        struct dev_exception_item *ex, *tmp;
 
        list_for_each_entry_safe(ex, tmp, &dev_cgroup->exceptions, list) {
-               list_del(&ex->list);
-               kfree(ex);
+               list_del_rcu(&ex->list);
+               kfree_rcu(ex, rcu);
        }
 }
 
@@ -182,13 +185,13 @@ static struct cgroup_subsys_state *devcgroup_create(struct cgroup *cgroup)
        parent_cgroup = cgroup->parent;
 
        if (parent_cgroup == NULL)
-               dev_cgroup->deny_all = false;
+               dev_cgroup->behavior = DEVCG_DEFAULT_ALLOW;
        else {
                parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup);
                mutex_lock(&devcgroup_mutex);
                ret = dev_exceptions_copy(&dev_cgroup->exceptions,
                                          &parent_dev_cgroup->exceptions);
-               dev_cgroup->deny_all = parent_dev_cgroup->deny_all;
+               dev_cgroup->behavior = parent_dev_cgroup->behavior;
                mutex_unlock(&devcgroup_mutex);
                if (ret) {
                        kfree(dev_cgroup);
@@ -260,7 +263,7 @@ static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft,
         * - List the exceptions in case the default policy is to deny
         * This way, the file remains as a "whitelist of devices"
         */
-       if (devcgroup->deny_all == false) {
+       if (devcgroup->behavior == DEVCG_DEFAULT_ALLOW) {
                set_access(acc, ACC_MASK);
                set_majmin(maj, ~0);
                set_majmin(min, ~0);
@@ -295,7 +298,7 @@ static int may_access(struct dev_cgroup *dev_cgroup,
        struct dev_exception_item *ex;
        bool match = false;
 
-       list_for_each_entry(ex, &dev_cgroup->exceptions, list) {
+       list_for_each_entry_rcu(ex, &dev_cgroup->exceptions, list) {
                if ((refex->type & DEV_BLOCK) && !(ex->type & DEV_BLOCK))
                        continue;
                if ((refex->type & DEV_CHAR) && !(ex->type & DEV_CHAR))
@@ -314,12 +317,12 @@ static int may_access(struct dev_cgroup *dev_cgroup,
         * In two cases we'll consider this new exception valid:
         * - the dev cgroup has its default policy to allow + exception list:
         *   the new exception should *not* match any of the exceptions
-        *   (!deny_all, !match)
+        *   (behavior == DEVCG_DEFAULT_ALLOW, !match)
         * - the dev cgroup has its default policy to deny + exception list:
         *   the new exception *should* match the exceptions
-        *   (deny_all, match)
+        *   (behavior == DEVCG_DEFAULT_DENY, match)
         */
-       if (dev_cgroup->deny_all == match)
+       if ((dev_cgroup->behavior == DEVCG_DEFAULT_DENY) == match)
                return 1;
        return 0;
 }
@@ -341,6 +344,19 @@ static int parent_has_perm(struct dev_cgroup *childcg,
        return may_access(parent, ex);
 }
 
+/**
+ * may_allow_all - checks if it's possible to change the behavior to
+ *                allow based on parent's rules.
+ * @parent: device cgroup's parent
+ * returns: != 0 in case it's allowed, 0 otherwise
+ */
+static inline int may_allow_all(struct dev_cgroup *parent)
+{
+       if (!parent)
+               return 1;
+       return parent->behavior == DEVCG_DEFAULT_ALLOW;
+}
+
 /*
  * Modify the exception list using allow/deny rules.
  * CAP_SYS_ADMIN is needed for this.  It's at least separate from CAP_MKNOD
@@ -358,13 +374,18 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
                                   int filetype, const char *buffer)
 {
        const char *b;
-       char *endp;
-       int count;
+       char temp[12];          /* 11 + 1 characters needed for a u32 */
+       int count, rc;
        struct dev_exception_item ex;
+       struct cgroup *p = devcgroup->css.cgroup;
+       struct dev_cgroup *parent = NULL;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
+       if (p->parent)
+               parent = cgroup_to_devcgroup(p->parent);
+
        memset(&ex, 0, sizeof(ex));
        b = buffer;
 
@@ -372,14 +393,21 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
        case 'a':
                switch (filetype) {
                case DEVCG_ALLOW:
-                       if (!parent_has_perm(devcgroup, &ex))
+                       if (!may_allow_all(parent))
                                return -EPERM;
                        dev_exception_clean(devcgroup);
-                       devcgroup->deny_all = false;
+                       devcgroup->behavior = DEVCG_DEFAULT_ALLOW;
+                       if (!parent)
+                               break;
+
+                       rc = dev_exceptions_copy(&devcgroup->exceptions,
+                                                &parent->exceptions);
+                       if (rc)
+                               return rc;
                        break;
                case DEVCG_DENY:
                        dev_exception_clean(devcgroup);
-                       devcgroup->deny_all = true;
+                       devcgroup->behavior = DEVCG_DEFAULT_DENY;
                        break;
                default:
                        return -EINVAL;
@@ -402,8 +430,16 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
                ex.major = ~0;
                b++;
        } else if (isdigit(*b)) {
-               ex.major = simple_strtoul(b, &endp, 10);
-               b = endp;
+               memset(temp, 0, sizeof(temp));
+               for (count = 0; count < sizeof(temp) - 1; count++) {
+                       temp[count] = *b;
+                       b++;
+                       if (!isdigit(*b))
+                               break;
+               }
+               rc = kstrtou32(temp, 10, &ex.major);
+               if (rc)
+                       return -EINVAL;
        } else {
                return -EINVAL;
        }
@@ -416,8 +452,16 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
                ex.minor = ~0;
                b++;
        } else if (isdigit(*b)) {
-               ex.minor = simple_strtoul(b, &endp, 10);
-               b = endp;
+               memset(temp, 0, sizeof(temp));
+               for (count = 0; count < sizeof(temp) - 1; count++) {
+                       temp[count] = *b;
+                       b++;
+                       if (!isdigit(*b))
+                               break;
+               }
+               rc = kstrtou32(temp, 10, &ex.minor);
+               if (rc)
+                       return -EINVAL;
        } else {
                return -EINVAL;
        }
@@ -452,7 +496,7 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
                 * an matching exception instead. And be silent about it: we
                 * don't want to break compatibility
                 */
-               if (devcgroup->deny_all == false) {
+               if (devcgroup->behavior == DEVCG_DEFAULT_ALLOW) {
                        dev_exception_rm(devcgroup, &ex);
                        return 0;
                }
@@ -463,7 +507,7 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
                 * an matching exception instead. And be silent about it: we
                 * don't want to break compatibility
                 */
-               if (devcgroup->deny_all == true) {
+               if (devcgroup->behavior == DEVCG_DEFAULT_DENY) {
                        dev_exception_rm(devcgroup, &ex);
                        return 0;
                }
@@ -533,10 +577,10 @@ struct cgroup_subsys devices_subsys = {
  *
  * returns 0 on success, -EPERM case the operation is not permitted
  */
-static int __devcgroup_check_permission(struct dev_cgroup *dev_cgroup,
-                                       short type, u32 major, u32 minor,
+static int __devcgroup_check_permission(short type, u32 major, u32 minor,
                                        short access)
 {
+       struct dev_cgroup *dev_cgroup;
        struct dev_exception_item ex;
        int rc;
 
@@ -547,6 +591,7 @@ static int __devcgroup_check_permission(struct dev_cgroup *dev_cgroup,
        ex.access = access;
 
        rcu_read_lock();
+       dev_cgroup = task_devcgroup(current);
        rc = may_access(dev_cgroup, &ex);
        rcu_read_unlock();
 
@@ -558,7 +603,6 @@ static int __devcgroup_check_permission(struct dev_cgroup *dev_cgroup,
 
 int __devcgroup_inode_permission(struct inode *inode, int mask)
 {
-       struct dev_cgroup *dev_cgroup = task_devcgroup(current);
        short type, access = 0;
 
        if (S_ISBLK(inode->i_mode))
@@ -570,13 +614,12 @@ int __devcgroup_inode_permission(struct inode *inode, int mask)
        if (mask & MAY_READ)
                access |= ACC_READ;
 
-       return __devcgroup_check_permission(dev_cgroup, type, imajor(inode),
-                                           iminor(inode), access);
+       return __devcgroup_check_permission(type, imajor(inode), iminor(inode),
+                       access);
 }
 
 int devcgroup_inode_mknod(int mode, dev_t dev)
 {
-       struct dev_cgroup *dev_cgroup = task_devcgroup(current);
        short type;
 
        if (!S_ISBLK(mode) && !S_ISCHR(mode))
@@ -587,7 +630,7 @@ int devcgroup_inode_mknod(int mode, dev_t dev)
        else
                type = DEV_CHAR;
 
-       return __devcgroup_check_permission(dev_cgroup, type, MAJOR(dev),
-                                           MINOR(dev), ACC_MKNOD);
+       return __devcgroup_check_permission(type, MAJOR(dev), MINOR(dev),
+                       ACC_MKNOD);
 
 }
index 24ab414..61a5336 100644 (file)
@@ -2132,18 +2132,14 @@ static inline void flush_unauthorized_files(const struct cred *cred,
                return;
 
        devnull = dentry_open(&selinux_null, O_RDWR, cred);
-       if (!IS_ERR(devnull)) {
-               /* replace all the matching ones with this */
-               do {
-                       replace_fd(n - 1, get_file(devnull), 0);
-               } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
+       if (IS_ERR(devnull))
+               devnull = NULL;
+       /* replace all the matching ones with this */
+       do {
+               replace_fd(n - 1, devnull, 0);
+       } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
+       if (devnull)
                fput(devnull);
-       } else {
-               /* just close all the matching ones */
-               do {
-                       replace_fd(n - 1, NULL, 0);
-               } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
-       }
 }
 
 /*
index 28f911c..c5454c0 100644 (file)
@@ -174,7 +174,8 @@ static void sel_netnode_insert(struct sel_netnode *node)
        if (sel_netnode_hash[idx].size == SEL_NETNODE_HASH_BKT_LIMIT) {
                struct sel_netnode *tail;
                tail = list_entry(
-                       rcu_dereference(sel_netnode_hash[idx].list.prev),
+                       rcu_dereference_protected(sel_netnode_hash[idx].list.prev,
+                                                 lockdep_is_held(&sel_netnode_lock)),
                        struct sel_netnode, list);
                list_del_rcu(&tail->list);
                kfree_rcu(tail, rcu);
index c40ae57..ad11dc9 100644 (file)
@@ -100,12 +100,15 @@ static int snd_compr_open(struct inode *inode, struct file *f)
 
        if (dirn != compr->direction) {
                pr_err("this device doesn't support this direction\n");
+               snd_card_unref(compr->card);
                return -EINVAL;
        }
 
        data = kzalloc(sizeof(*data), GFP_KERNEL);
-       if (!data)
+       if (!data) {
+               snd_card_unref(compr->card);
                return -ENOMEM;
+       }
        data->stream.ops = compr->ops;
        data->stream.direction = dirn;
        data->stream.private_data = compr->private_data;
@@ -113,6 +116,7 @@ static int snd_compr_open(struct inode *inode, struct file *f)
        runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
        if (!runtime) {
                kfree(data);
+               snd_card_unref(compr->card);
                return -ENOMEM;
        }
        runtime->state = SNDRV_PCM_STATE_OPEN;
@@ -126,7 +130,8 @@ static int snd_compr_open(struct inode *inode, struct file *f)
                kfree(runtime);
                kfree(data);
        }
-       return ret;
+       snd_card_unref(compr->card);
+       return 0;
 }
 
 static int snd_compr_free(struct inode *inode, struct file *f)
index 7e86a5b..8c7c2c9 100644 (file)
@@ -86,6 +86,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
        write_lock_irqsave(&card->ctl_files_rwlock, flags);
        list_add_tail(&ctl->list, &card->ctl_files);
        write_unlock_irqrestore(&card->ctl_files_rwlock, flags);
+       snd_card_unref(card);
        return 0;
 
       __error:
@@ -93,6 +94,8 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
       __error2:
        snd_card_file_remove(card, file);
       __error1:
+       if (card)
+               snd_card_unref(card);
        return err;
 }
 
@@ -1434,6 +1437,8 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer,
                        spin_unlock_irq(&ctl->read_lock);
                        schedule();
                        remove_wait_queue(&ctl->change_sleep, &wait);
+                       if (ctl->card->shutdown)
+                               return -ENODEV;
                        if (signal_pending(current))
                                return -ERESTARTSYS;
                        spin_lock_irq(&ctl->read_lock);
index 75ea16f..3f7f662 100644 (file)
@@ -100,8 +100,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
        if (hw == NULL)
                return -ENODEV;
 
-       if (!try_module_get(hw->card->module))
+       if (!try_module_get(hw->card->module)) {
+               snd_card_unref(hw->card);
                return -EFAULT;
+       }
 
        init_waitqueue_entry(&wait, current);
        add_wait_queue(&hw->open_wait, &wait);
@@ -129,6 +131,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
                mutex_unlock(&hw->open_mutex);
                schedule();
                mutex_lock(&hw->open_mutex);
+               if (hw->card->shutdown) {
+                       err = -ENODEV;
+                       break;
+               }
                if (signal_pending(current)) {
                        err = -ERESTARTSYS;
                        break;
@@ -148,6 +154,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
        mutex_unlock(&hw->open_mutex);
        if (err < 0)
                module_put(hw->card->module);
+       snd_card_unref(hw->card);
        return err;
 }
 
@@ -459,12 +466,15 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device)
                mutex_unlock(&register_mutex);
                return -EINVAL;
        }
+       mutex_lock(&hwdep->open_mutex);
+       wake_up(&hwdep->open_wait);
 #ifdef CONFIG_SND_OSSEMUL
        if (hwdep->ossreg)
                snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device);
 #endif
        snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device);
        list_del_init(&hwdep->list);
+       mutex_unlock(&hwdep->open_mutex);
        mutex_unlock(&register_mutex);
        return 0;
 }
index d8ec849..7b012d1 100644 (file)
@@ -213,6 +213,7 @@ int snd_card_create(int idx, const char *xid,
        spin_lock_init(&card->files_lock);
        INIT_LIST_HEAD(&card->files_list);
        init_waitqueue_head(&card->shutdown_sleep);
+       atomic_set(&card->refcount, 0);
 #ifdef CONFIG_PM
        mutex_init(&card->power_lock);
        init_waitqueue_head(&card->power_sleep);
@@ -446,21 +447,36 @@ static int snd_card_do_free(struct snd_card *card)
        return 0;
 }
 
+/**
+ * snd_card_unref - release the reference counter
+ * @card: the card instance
+ *
+ * Decrements the reference counter.  When it reaches to zero, wake up
+ * the sleeper and call the destructor if needed.
+ */
+void snd_card_unref(struct snd_card *card)
+{
+       if (atomic_dec_and_test(&card->refcount)) {
+               wake_up(&card->shutdown_sleep);
+               if (card->free_on_last_close)
+                       snd_card_do_free(card);
+       }
+}
+EXPORT_SYMBOL(snd_card_unref);
+
 int snd_card_free_when_closed(struct snd_card *card)
 {
-       int free_now = 0;
-       int ret = snd_card_disconnect(card);
-       if (ret)
-               return ret;
+       int ret;
 
-       spin_lock(&card->files_lock);
-       if (list_empty(&card->files_list))
-               free_now = 1;
-       else
-               card->free_on_last_close = 1;
-       spin_unlock(&card->files_lock);
+       atomic_inc(&card->refcount);
+       ret = snd_card_disconnect(card);
+       if (ret) {
+               atomic_dec(&card->refcount);
+               return ret;
+       }
 
-       if (free_now)
+       card->free_on_last_close = 1;
+       if (atomic_dec_and_test(&card->refcount))
                snd_card_do_free(card);
        return 0;
 }
@@ -474,7 +490,7 @@ int snd_card_free(struct snd_card *card)
                return ret;
 
        /* wait, until all devices are ready for the free operation */
-       wait_event(card->shutdown_sleep, list_empty(&card->files_list));
+       wait_event(card->shutdown_sleep, !atomic_read(&card->refcount));
        snd_card_do_free(card);
        return 0;
 }
@@ -886,6 +902,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file)
                return -ENODEV;
        }
        list_add(&mfile->list, &card->files_list);
+       atomic_inc(&card->refcount);
        spin_unlock(&card->files_lock);
        return 0;
 }
@@ -908,7 +925,6 @@ EXPORT_SYMBOL(snd_card_file_add);
 int snd_card_file_remove(struct snd_card *card, struct file *file)
 {
        struct snd_monitor_file *mfile, *found = NULL;
-       int last_close = 0;
 
        spin_lock(&card->files_lock);
        list_for_each_entry(mfile, &card->files_list, list) {
@@ -923,19 +939,13 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
                        break;
                }
        }
-       if (list_empty(&card->files_list))
-               last_close = 1;
        spin_unlock(&card->files_lock);
-       if (last_close) {
-               wake_up(&card->shutdown_sleep);
-               if (card->free_on_last_close)
-                       snd_card_do_free(card);
-       }
        if (!found) {
                snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file);
                return -ENOENT;
        }
        kfree(found);
+       snd_card_unref(card);
        return 0;
 }
 
index 29f6ded..e8a1d18 100644 (file)
@@ -52,14 +52,19 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)
                                         SNDRV_OSS_DEVICE_TYPE_MIXER);
        if (card == NULL)
                return -ENODEV;
-       if (card->mixer_oss == NULL)
+       if (card->mixer_oss == NULL) {
+               snd_card_unref(card);
                return -ENODEV;
+       }
        err = snd_card_file_add(card, file);
-       if (err < 0)
+       if (err < 0) {
+               snd_card_unref(card);
                return err;
+       }
        fmixer = kzalloc(sizeof(*fmixer), GFP_KERNEL);
        if (fmixer == NULL) {
                snd_card_file_remove(card, file);
+               snd_card_unref(card);
                return -ENOMEM;
        }
        fmixer->card = card;
@@ -68,8 +73,10 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)
        if (!try_module_get(card->module)) {
                kfree(fmixer);
                snd_card_file_remove(card, file);
+               snd_card_unref(card);
                return -EFAULT;
        }
+       snd_card_unref(card);
        return 0;
 }
 
index 08fde00..4c1cc51 100644 (file)
@@ -2441,6 +2441,10 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
                mutex_unlock(&pcm->open_mutex);
                schedule();
                mutex_lock(&pcm->open_mutex);
+               if (pcm->card->shutdown) {
+                       err = -ENODEV;
+                       break;
+               }
                if (signal_pending(current)) {
                        err = -ERESTARTSYS;
                        break;
@@ -2450,6 +2454,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
        mutex_unlock(&pcm->open_mutex);
        if (err < 0)
                goto __error;
+       snd_card_unref(pcm->card);
        return err;
 
       __error:
@@ -2457,6 +2462,8 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
       __error2:
        snd_card_file_remove(pcm->card, file);
       __error1:
+       if (pcm)
+               snd_card_unref(pcm->card);
        return err;
 }
 
index f299194..030102c 100644 (file)
@@ -1086,11 +1086,19 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
        if (list_empty(&pcm->list))
                goto unlock;
 
+       mutex_lock(&pcm->open_mutex);
+       wake_up(&pcm->open_wait);
        list_del_init(&pcm->list);
        for (cidx = 0; cidx < 2; cidx++)
-               for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
-                       if (substream->runtime)
+               for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) {
+                       snd_pcm_stream_lock_irq(substream);
+                       if (substream->runtime) {
                                substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED;
+                               wake_up(&substream->runtime->sleep);
+                               wake_up(&substream->runtime->tsleep);
+                       }
+                       snd_pcm_stream_unlock_irq(substream);
+               }
        list_for_each_entry(notify, &snd_pcm_notify_list, list) {
                notify->n_disconnect(pcm);
        }
@@ -1110,6 +1118,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
                        pcm->streams[cidx].chmap_kctl = NULL;
                }
        }
+       mutex_unlock(&pcm->open_mutex);
  unlock:
        mutex_unlock(&register_mutex);
        return 0;
index 5e12e5b..f9ddecf 100644 (file)
@@ -369,6 +369,14 @@ static int period_to_usecs(struct snd_pcm_runtime *runtime)
        return usecs;
 }
 
+static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state)
+{
+       snd_pcm_stream_lock_irq(substream);
+       if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED)
+               substream->runtime->status->state = state;
+       snd_pcm_stream_unlock_irq(substream);
+}
+
 static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
                             struct snd_pcm_hw_params *params)
 {
@@ -452,7 +460,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
                runtime->boundary *= 2;
 
        snd_pcm_timer_resolution_change(substream);
-       runtime->status->state = SNDRV_PCM_STATE_SETUP;
+       snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP);
 
        if (pm_qos_request_active(&substream->latency_pm_qos_req))
                pm_qos_remove_request(&substream->latency_pm_qos_req);
@@ -464,7 +472,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
        /* hardware might be unusable from this time,
           so we force application to retry to set
           the correct hardware parameter settings */
-       runtime->status->state = SNDRV_PCM_STATE_OPEN;
+       snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
        if (substream->ops->hw_free != NULL)
                substream->ops->hw_free(substream);
        return err;
@@ -512,7 +520,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
                return -EBADFD;
        if (substream->ops->hw_free)
                result = substream->ops->hw_free(substream);
-       runtime->status->state = SNDRV_PCM_STATE_OPEN;
+       snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
        pm_qos_remove_request(&substream->latency_pm_qos_req);
        return result;
 }
@@ -1320,7 +1328,7 @@ static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        runtime->control->appl_ptr = runtime->status->hw_ptr;
-       runtime->status->state = SNDRV_PCM_STATE_PREPARED;
+       snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED);
 }
 
 static struct action_ops snd_pcm_action_prepare = {
@@ -1510,6 +1518,10 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
                down_read(&snd_pcm_link_rwsem);
                snd_pcm_stream_lock_irq(substream);
                remove_wait_queue(&to_check->sleep, &wait);
+               if (card->shutdown) {
+                       result = -ENODEV;
+                       break;
+               }
                if (tout == 0) {
                        if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
                                result = -ESTRPIPE;
@@ -1634,6 +1646,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
        write_unlock_irq(&snd_pcm_link_rwlock);
        up_write(&snd_pcm_link_rwsem);
  _nolock:
+       snd_card_unref(substream1->pcm->card);
        fput_light(file, fput_needed);
        if (res < 0)
                kfree(group);
@@ -2108,7 +2121,10 @@ static int snd_pcm_playback_open(struct inode *inode, struct file *file)
                return err;
        pcm = snd_lookup_minor_data(iminor(inode),
                                    SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
-       return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);
+       err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);
+       if (pcm)
+               snd_card_unref(pcm->card);
+       return err;
 }
 
 static int snd_pcm_capture_open(struct inode *inode, struct file *file)
@@ -2119,7 +2135,10 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file)
                return err;
        pcm = snd_lookup_minor_data(iminor(inode),
                                    SNDRV_DEVICE_TYPE_PCM_CAPTURE);
-       return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);
+       err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);
+       if (pcm)
+               snd_card_unref(pcm->card);
+       return err;
 }
 
 static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
@@ -2156,6 +2175,10 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
                mutex_unlock(&pcm->open_mutex);
                schedule();
                mutex_lock(&pcm->open_mutex);
+               if (pcm->card->shutdown) {
+                       err = -ENODEV;
+                       break;
+               }
                if (signal_pending(current)) {
                        err = -ERESTARTSYS;
                        break;
index ebf6e49..1bb95ae 100644 (file)
@@ -379,8 +379,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
        if (rmidi == NULL)
                return -ENODEV;
 
-       if (!try_module_get(rmidi->card->module))
+       if (!try_module_get(rmidi->card->module)) {
+               snd_card_unref(rmidi->card);
                return -ENXIO;
+       }
 
        mutex_lock(&rmidi->open_mutex);
        card = rmidi->card;
@@ -422,6 +424,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
                mutex_unlock(&rmidi->open_mutex);
                schedule();
                mutex_lock(&rmidi->open_mutex);
+               if (rmidi->card->shutdown) {
+                       err = -ENODEV;
+                       break;
+               }
                if (signal_pending(current)) {
                        err = -ERESTARTSYS;
                        break;
@@ -440,6 +446,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
 #endif
        file->private_data = rawmidi_file;
        mutex_unlock(&rmidi->open_mutex);
+       snd_card_unref(rmidi->card);
        return 0;
 
  __error:
@@ -447,6 +454,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
  __error_card:
        mutex_unlock(&rmidi->open_mutex);
        module_put(rmidi->card->module);
+       snd_card_unref(rmidi->card);
        return err;
 }
 
@@ -991,6 +999,8 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun
                        spin_unlock_irq(&runtime->lock);
                        schedule();
                        remove_wait_queue(&runtime->sleep, &wait);
+                       if (rfile->rmidi->card->shutdown)
+                               return -ENODEV;
                        if (signal_pending(current))
                                return result > 0 ? result : -ERESTARTSYS;
                        if (!runtime->avail)
@@ -1234,6 +1244,8 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf,
                        spin_unlock_irq(&runtime->lock);
                        timeout = schedule_timeout(30 * HZ);
                        remove_wait_queue(&runtime->sleep, &wait);
+                       if (rfile->rmidi->card->shutdown)
+                               return -ENODEV;
                        if (signal_pending(current))
                                return result > 0 ? result : -ERESTARTSYS;
                        if (!runtime->avail && !timeout)
@@ -1609,9 +1621,20 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
 static int snd_rawmidi_dev_disconnect(struct snd_device *device)
 {
        struct snd_rawmidi *rmidi = device->device_data;
+       int dir;
 
        mutex_lock(&register_mutex);
+       mutex_lock(&rmidi->open_mutex);
+       wake_up(&rmidi->open_wait);
        list_del_init(&rmidi->list);
+       for (dir = 0; dir < 2; dir++) {
+               struct snd_rawmidi_substream *s;
+               list_for_each_entry(s, &rmidi->streams[dir].substreams, list) {
+                       if (s->runtime)
+                               wake_up(&s->runtime->sleep);
+               }
+       }
+
 #ifdef CONFIG_SND_OSSEMUL
        if (rmidi->ossreg) {
                if ((int)rmidi->device == midi_map[rmidi->card->number]) {
@@ -1626,6 +1649,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device)
        }
 #endif /* CONFIG_SND_OSSEMUL */
        snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device);
+       mutex_unlock(&rmidi->open_mutex);
        mutex_unlock(&register_mutex);
        return 0;
 }
index 6439760..70ccdab 100644 (file)
@@ -98,6 +98,10 @@ static void snd_request_other(int minor)
  *
  * Checks that a minor device with the specified type is registered, and returns
  * its user data pointer.
+ *
+ * This function increments the reference counter of the card instance
+ * if an associated instance with the given minor number and type is found.
+ * The caller must call snd_card_unref() appropriately later.
  */
 void *snd_lookup_minor_data(unsigned int minor, int type)
 {
@@ -108,9 +112,11 @@ void *snd_lookup_minor_data(unsigned int minor, int type)
                return NULL;
        mutex_lock(&sound_mutex);
        mreg = snd_minors[minor];
-       if (mreg && mreg->type == type)
+       if (mreg && mreg->type == type) {
                private_data = mreg->private_data;
-       else
+               if (private_data && mreg->card_ptr)
+                       atomic_inc(&mreg->card_ptr->refcount);
+       } else
                private_data = NULL;
        mutex_unlock(&sound_mutex);
        return private_data;
@@ -275,6 +281,7 @@ int snd_register_device_for_dev(int type, struct snd_card *card, int dev,
        preg->device = dev;
        preg->f_ops = f_ops;
        preg->private_data = private_data;
+       preg->card_ptr = card;
        mutex_lock(&sound_mutex);
 #ifdef CONFIG_SND_DYNAMIC_MINORS
        minor = snd_find_free_minor(type);
index e952833..726a49a 100644 (file)
@@ -40,6 +40,9 @@
 static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS];
 static DEFINE_MUTEX(sound_oss_mutex);
 
+/* NOTE: This function increments the refcount of the associated card like
+ * snd_lookup_minor_data(); the caller must call snd_card_unref() appropriately
+ */
 void *snd_lookup_oss_minor_data(unsigned int minor, int type)
 {
        struct snd_minor *mreg;
@@ -49,9 +52,11 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type)
                return NULL;
        mutex_lock(&sound_oss_mutex);
        mreg = snd_oss_minors[minor];
-       if (mreg && mreg->type == type)
+       if (mreg && mreg->type == type) {
                private_data = mreg->private_data;
-       else
+               if (private_data && mreg->card_ptr)
+                       atomic_inc(&mreg->card_ptr->refcount);
+       } else
                private_data = NULL;
        mutex_unlock(&sound_oss_mutex);
        return private_data;
@@ -123,6 +128,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
        preg->device = dev;
        preg->f_ops = f_ops;
        preg->private_data = private_data;
+       preg->card_ptr = card;
        mutex_lock(&sound_oss_mutex);
        snd_oss_minors[minor] = preg;
        minor_unit = SNDRV_MINOR_OSS_DEVICE(minor);
index ef68d71..e04e750 100644 (file)
@@ -426,7 +426,7 @@ static struct snd_kcontrol_new snd_ak4113_iec958_controls[] = {
 },
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
-       .name =         "IEC958 Preample Capture Default",
+       .name =         "IEC958 Preamble Capture Default",
        .access =       SNDRV_CTL_ELEM_ACCESS_READ |
                SNDRV_CTL_ELEM_ACCESS_VOLATILE,
        .info =         snd_ak4113_spdif_pinfo,
index 816e7d2..5bf4fca 100644 (file)
@@ -401,7 +401,7 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = {
 },
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
-       .name =         "IEC958 Preample Capture Default",
+       .name =         "IEC958 Preamble Capture Default",
        .access =       SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
        .info =         snd_ak4114_spdif_pinfo,
        .get =          snd_ak4114_spdif_pget,
index b4b2a51..40e33c9 100644 (file)
@@ -380,7 +380,7 @@ static struct snd_kcontrol_new snd_ak4117_iec958_controls[] = {
 },
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
-       .name =         "IEC958 Preample Capture Default",
+       .name =         "IEC958 Preamble Capture Default",
        .access =       SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
        .info =         snd_ak4117_spdif_pinfo,
        .get =          snd_ak4117_spdif_pget,
index 3d1afb6..4a7ff4e 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 9473fca..8b0f996 100644 (file)
@@ -1271,6 +1271,8 @@ static int snd_ac97_cvol_new(struct snd_card *card, char *name, int reg, unsigne
                tmp.index = ac97->num;
                kctl = snd_ctl_new1(&tmp, ac97);
        }
+       if (!kctl)
+               return -ENOMEM;
        if (reg >= AC97_PHONE && reg <= AC97_PCM)
                set_tlv_db_scale(kctl, db_scale_5bit_12db_max);
        else
index 00f157a..5af3cb6 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 bed4485..c21adb6 100644 (file)
@@ -1416,6 +1416,15 @@ static struct snd_emu_chip_details emu_chip_details[] = {
         .ca0108_chip = 1,
         .spk71 = 1,
         .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 new revision */
+       /* Tested by Maxim Kachur <mcdebugger@duganet.ru> 17th Oct 2012. */
+       /* This is MAEM8986, 0202 is MAEM8980 */
+       {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40071102,
+        .driver = "Audigy2", .name = "E-mu 1010 PCIe [MAEM8986]",
+        .id = "EMU1010",
+        .emu10k2_chip = 1,
+        .ca0108_chip = 1,
+        .spk71 = 1,
+        .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 PCIe */
        /* Tested by James@superbug.co.uk 8th July 2005. */
        /* This is MAEM8810, 0202 is MAEM8820 */
        {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102,
index 5d0e568..7266020 100644 (file)
@@ -2581,9 +2581,14 @@ static u8 snd_es1968_tea575x_get_pins(struct snd_tea575x *tea)
        struct es1968 *chip = tea->private_data;
        unsigned long io = chip->io_port + GPIO_DATA;
        u16 val = inw(io);
+       u8 ret;
 
-       return  (val & STR_DATA) ? TEA575X_DATA : 0 |
-               (val & STR_MOST) ? TEA575X_MOST : 0;
+       ret = 0;
+       if (val & STR_DATA)
+               ret |= TEA575X_DATA;
+       if (val & STR_MOST)
+               ret |= TEA575X_MOST;
+       return ret;
 }
 
 static void snd_es1968_tea575x_set_direction(struct snd_tea575x *tea, bool output)
@@ -2655,6 +2660,8 @@ static struct ess_device_list pm_whitelist[] __devinitdata = {
        { TYPE_MAESTRO2E, 0x1179 },
        { TYPE_MAESTRO2E, 0x14c0 },     /* HP omnibook 4150 */
        { TYPE_MAESTRO2E, 0x1558 },
+       { TYPE_MAESTRO2E, 0x125d },     /* a PCI card, e.g. Terratec DMX */
+       { TYPE_MAESTRO2, 0x125d },      /* a PCI card, e.g. SF64-PCE2 */
 };
 
 static struct ess_device_list mpu_blacklist[] __devinitdata = {
index cc2e91d..c5806f8 100644 (file)
@@ -767,9 +767,14 @@ static u8 snd_fm801_tea575x_get_pins(struct snd_tea575x *tea)
        struct fm801 *chip = tea->private_data;
        unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL));
        struct snd_fm801_tea575x_gpio gpio = *get_tea575x_gpio(chip);
-
-       return  (reg & FM801_GPIO_GP(gpio.data)) ? TEA575X_DATA : 0 |
-               (reg & FM801_GPIO_GP(gpio.most)) ? TEA575X_MOST : 0;
+       u8 ret;
+
+       ret = 0;
+       if (reg & FM801_GPIO_GP(gpio.data))
+               ret |= TEA575X_DATA;
+       if (reg & FM801_GPIO_GP(gpio.most))
+               ret |= TEA575X_MOST;
+       return ret;
 }
 
 static void snd_fm801_tea575x_set_direction(struct snd_tea575x *tea, bool output)
index 70d4848..d010de1 100644 (file)
@@ -95,6 +95,7 @@ int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
 EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
 
 #ifdef CONFIG_PM
+#define codec_in_pm(codec)     ((codec)->in_pm)
 static void hda_power_work(struct work_struct *work);
 static void hda_keep_power_on(struct hda_codec *codec);
 #define hda_codec_is_power_on(codec)   ((codec)->power_on)
@@ -104,6 +105,7 @@ static inline void hda_call_pm_notify(struct hda_bus *bus, bool power_up)
                bus->ops.pm_notify(bus, power_up);
 }
 #else
+#define codec_in_pm(codec)     0
 static inline void hda_keep_power_on(struct hda_codec *codec) {}
 #define hda_codec_is_power_on(codec)   1
 #define hda_call_pm_notify(bus, state) {}
@@ -228,7 +230,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
        }
        mutex_unlock(&bus->cmd_mutex);
        snd_hda_power_down(codec);
-       if (res && *res == -1 && bus->rirb_error) {
+       if (!codec_in_pm(codec) && res && *res == -1 && bus->rirb_error) {
                if (bus->response_reset) {
                        snd_printd("hda_codec: resetting BUS due to "
                                   "fatal communication error\n");
@@ -238,7 +240,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
                goto again;
        }
        /* clear reset-flag when the communication gets recovered */
-       if (!err)
+       if (!err || codec_in_pm(codec))
                bus->response_reset = 0;
        return err;
 }
@@ -3616,6 +3618,8 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq)
 {
        unsigned int state;
 
+       codec->in_pm = 1;
+
        if (codec->patch_ops.suspend)
                codec->patch_ops.suspend(codec);
        hda_cleanup_all_streams(codec);
@@ -3630,6 +3634,7 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq)
        codec->power_transition = 0;
        codec->power_jiffies = jiffies;
        spin_unlock(&codec->power_lock);
+       codec->in_pm = 0;
        return state;
 }
 
@@ -3638,6 +3643,8 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq)
  */
 static void hda_call_codec_resume(struct hda_codec *codec)
 {
+       codec->in_pm = 1;
+
        /* set as if powered on for avoiding re-entering the resume
         * in the resume / power-save sequence
         */
@@ -3656,6 +3663,8 @@ static void hda_call_codec_resume(struct hda_codec *codec)
                snd_hda_codec_resume_cache(codec);
        }
        snd_hda_jack_report_sync(codec);
+
+       codec->in_pm = 0;
        snd_hda_power_down(codec); /* flag down before returning */
 }
 #endif /* CONFIG_PM */
index 507fe8a..4f4e545 100644 (file)
@@ -869,6 +869,7 @@ struct hda_codec {
        unsigned int power_on :1;       /* current (global) power-state */
        unsigned int d3_stop_clk:1;     /* support D3 operation without BCLK */
        unsigned int pm_down_notified:1; /* PM notified to controller */
+       unsigned int in_pm:1;           /* suspend/resume being performed */
        int power_transition;   /* power-state in transition */
        int power_count;        /* current (global) power refcount */
        struct delayed_work power_work; /* delayed task for powerdown */
index 6833835..f9d870e 100644 (file)
@@ -501,6 +501,7 @@ struct azx {
 
        /* VGA-switcheroo setup */
        unsigned int use_vga_switcheroo:1;
+       unsigned int vga_switcheroo_registered:1;
        unsigned int init_failed:1; /* delayed init failed */
        unsigned int disabled:1; /* disabled by VGA-switcher */
 
@@ -555,6 +556,12 @@ enum {
 #define AZX_DCAPS_ALIGN_BUFSIZE        (1 << 22)       /* buffer size alignment */
 #define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23)   /* BDLE in 4k boundary */
 #define AZX_DCAPS_COUNT_LPIB_DELAY  (1 << 25)  /* Take LPIB as delay */
+#define AZX_DCAPS_PM_RUNTIME   (1 << 26)       /* runtime PM support */
+
+/* quirks for Intel PCH */
+#define AZX_DCAPS_INTEL_PCH \
+       (AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_BUFSIZE | \
+        AZX_DCAPS_COUNT_LPIB_DELAY | AZX_DCAPS_PM_RUNTIME)
 
 /* quirks for ATI SB / AMD Hudson */
 #define AZX_DCAPS_PRESET_ATI_SB \
@@ -2157,9 +2164,12 @@ static unsigned int azx_get_position(struct azx *chip,
                if (delay < 0)
                        delay += azx_dev->bufsize;
                if (delay >= azx_dev->period_bytes) {
-                       snd_printdd("delay %d > period_bytes %d\n",
-                               delay, azx_dev->period_bytes);
-                       delay = 0; /* something is wrong */
+                       snd_printk(KERN_WARNING SFX
+                                  "Unstable LPIB (%d >= %d); "
+                                  "disabling LPIB delay counting\n",
+                                  delay, azx_dev->period_bytes);
+                       delay = 0;
+                       chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY;
                }
                azx_dev->substream->runtime->delay =
                        bytes_to_frames(azx_dev->substream->runtime, delay);
@@ -2429,6 +2439,9 @@ static void azx_power_notify(struct hda_bus *bus, bool power_up)
 {
        struct azx *chip = bus->private_data;
 
+       if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
+               return;
+
        if (power_up)
                pm_runtime_get_sync(&chip->pci->dev);
        else
@@ -2544,7 +2557,8 @@ static int azx_runtime_suspend(struct device *dev)
        struct snd_card *card = dev_get_drvdata(dev);
        struct azx *chip = card->private_data;
 
-       if (!power_save_controller)
+       if (!power_save_controller ||
+           !(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
                return -EAGAIN;
 
        azx_stop_chip(chip);
@@ -2640,7 +2654,9 @@ static void azx_vs_set_state(struct pci_dev *pci,
                if (disabled) {
                        azx_suspend(&pci->dev);
                        chip->disabled = true;
-                       snd_hda_lock_devices(chip->bus);
+                       if (snd_hda_lock_devices(chip->bus))
+                               snd_printk(KERN_WARNING SFX
+                                          "Cannot lock devices!\n");
                } else {
                        snd_hda_unlock_devices(chip->bus);
                        chip->disabled = false;
@@ -2683,14 +2699,20 @@ static const struct vga_switcheroo_client_ops azx_vs_ops = {
 
 static int __devinit register_vga_switcheroo(struct azx *chip)
 {
+       int err;
+
        if (!chip->use_vga_switcheroo)
                return 0;
        /* FIXME: currently only handling DIS controller
         * is there any machine with two switchable HDMI audio controllers?
         */
-       return vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops,
+       err = vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops,
                                                    VGA_SWITCHEROO_DIS,
                                                    chip->bus != NULL);
+       if (err < 0)
+               return err;
+       chip->vga_switcheroo_registered = 1;
+       return 0;
 }
 #else
 #define init_vga_switcheroo(chip)              /* NOP */
@@ -2712,7 +2734,8 @@ static int azx_free(struct azx *chip)
        if (use_vga_switcheroo(chip)) {
                if (chip->disabled && chip->bus)
                        snd_hda_unlock_devices(chip->bus);
-               vga_switcheroo_unregister_client(chip->pci);
+               if (chip->vga_switcheroo_registered)
+                       vga_switcheroo_unregister_client(chip->pci);
        }
 
        if (chip->initialized) {
@@ -2813,8 +2836,6 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = {
        SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB),
-       SND_PCI_QUIRK(0x1043, 0x1ac3, "ASUS X53S", POS_FIX_POSBUF),
-       SND_PCI_QUIRK(0x1043, 0x1b43, "ASUS K53E", POS_FIX_POSBUF),
        SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x10de, 0xcb89, "Macbook Pro 7,1", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB),
@@ -3062,14 +3083,6 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
        }
 
  ok:
-       err = register_vga_switcheroo(chip);
-       if (err < 0) {
-               snd_printk(KERN_ERR SFX
-                          "Error registering VGA-switcheroo client\n");
-               azx_free(chip);
-               return err;
-       }
-
        err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
        if (err < 0) {
                snd_printk(KERN_ERR SFX "Error creating device [card]!\n");
@@ -3340,6 +3353,13 @@ static int __devinit azx_probe(struct pci_dev *pci,
        if (pci_dev_run_wake(pci))
                pm_runtime_put_noidle(&pci->dev);
 
+       err = register_vga_switcheroo(chip);
+       if (err < 0) {
+               snd_printk(KERN_ERR SFX
+                          "Error registering VGA-switcheroo client\n");
+               goto out_free;
+       }
+
        dev++;
        return 0;
 
@@ -3419,39 +3439,30 @@ static void __devexit azx_remove(struct pci_dev *pci)
 static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
        /* CPT */
        { PCI_DEVICE(0x8086, 0x1c20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* PBG */
        { PCI_DEVICE(0x8086, 0x1d20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE},
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* Panther Point */
        { PCI_DEVICE(0x8086, 0x1e20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* Lynx Point */
        { PCI_DEVICE(0x8086, 0x8c20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* Lynx Point-LP */
        { PCI_DEVICE(0x8086, 0x9c20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* Lynx Point-LP */
        { PCI_DEVICE(0x8086, 0x9c21),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* Haswell */
        { PCI_DEVICE(0x8086, 0x0c0c),
-         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH },
        { PCI_DEVICE(0x8086, 0x0d0c),
-         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH },
        /* 5 Series/3400 */
        { PCI_DEVICE(0x8086, 0x3b56),
-         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH },
        /* SCH */
        { PCI_DEVICE(0x8086, 0x811b),
          .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
@@ -3553,6 +3564,8 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
        /* Teradici */
        { PCI_DEVICE(0x6549, 0x1200),
          .driver_data = AZX_DRIVER_TERA | AZX_DCAPS_NO_64BIT },
+       { PCI_DEVICE(0x6549, 0x2200),
+         .driver_data = AZX_DRIVER_TERA | AZX_DCAPS_NO_64BIT },
        /* Creative X-Fi (CA0110-IBG) */
        /* CTHDA chips */
        { PCI_DEVICE(0x1102, 0x0010),
index cdd43ea..1eeba73 100644 (file)
@@ -545,6 +545,7 @@ static int ad198x_build_pcms(struct hda_codec *codec)
        if (spec->multiout.dig_out_nid) {
                info++;
                codec->num_pcms++;
+               codec->spdif_status_reset = 1;
                info->name = "AD198x Digital";
                info->pcm_type = HDA_PCM_TYPE_SPDIF;
                info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
index 61a7113..3bcb671 100644 (file)
@@ -101,8 +101,8 @@ enum {
 #define CS420X_VENDOR_NID      0x11
 #define CS_DIG_OUT1_PIN_NID    0x10
 #define CS_DIG_OUT2_PIN_NID    0x15
-#define CS_DMIC1_PIN_NID       0x12
-#define CS_DMIC2_PIN_NID       0x0e
+#define CS_DMIC1_PIN_NID       0x0e
+#define CS_DMIC2_PIN_NID       0x12
 
 /* coef indices */
 #define IDX_SPDIF_STAT         0x0000
@@ -466,6 +466,7 @@ static int parse_output(struct hda_codec *codec)
                memcpy(cfg->speaker_pins, cfg->line_out_pins,
                       sizeof(cfg->speaker_pins));
                cfg->line_outs = 0;
+               memset(cfg->line_out_pins, 0, sizeof(cfg->line_out_pins));
        }
 
        return 0;
@@ -1079,14 +1080,18 @@ static void init_input(struct hda_codec *codec)
                        cs_automic(codec, NULL);
 
                coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */
+               cs_vendor_coef_set(codec, IDX_ADC_CFG, coef);
+
+               coef = cs_vendor_coef_get(codec, IDX_BEEP_CFG);
                if (is_active_pin(codec, CS_DMIC2_PIN_NID))
-                       coef |= 0x0500; /* DMIC2 2 chan on, GPIO1 off */
+                       coef |= 1 << 4; /* DMIC2 2 chan on, GPIO1 off */
                if (is_active_pin(codec, CS_DMIC1_PIN_NID))
-                       coef |= 0x1800; /* DMIC1 2 chan on, GPIO0 off
+                       coef |= 1 << 3; /* DMIC1 2 chan on, GPIO0 off
                                         * No effect if SPDIF_OUT2 is
                                         * selected in IDX_SPDIF_CTL.
                                        */
-               cs_vendor_coef_set(codec, IDX_ADC_CFG, coef);
+
+               cs_vendor_coef_set(codec, IDX_BEEP_CFG, coef);
        } else {
                if (spec->mic_detect)
                        cs_automic(codec, NULL);
@@ -1107,7 +1112,7 @@ static const struct hda_verb cs_coef_init_verbs[] = {
          | 0x0400 /* Disable Coefficient Auto increment */
          )},
        /* Beep */
-       {0x11, AC_VERB_SET_COEF_INDEX, IDX_DAC_CFG},
+       {0x11, AC_VERB_SET_COEF_INDEX, IDX_BEEP_CFG},
        {0x11, AC_VERB_SET_PROC_COEF, 0x0007}, /* Enable Beep thru DAC1/2/3 */
 
        {} /* terminator */
@@ -1728,8 +1733,7 @@ static int cs421x_mux_enum_put(struct snd_kcontrol *kcontrol,
 
 }
 
-static struct snd_kcontrol_new cs421x_capture_source = {
-
+static const struct snd_kcontrol_new cs421x_capture_source = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Capture Source",
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -1946,7 +1950,7 @@ static int cs421x_suspend(struct hda_codec *codec)
 }
 #endif
 
-static struct hda_codec_ops cs421x_patch_ops = {
+static const struct hda_codec_ops cs421x_patch_ops = {
        .build_controls = cs421x_build_controls,
        .build_pcms = cs_build_pcms,
        .init = cs421x_init,
index 8253b4e..ad68d22 100644 (file)
@@ -2598,8 +2598,10 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch,
                        return "PCM";
                break;
        }
-       if (snd_BUG_ON(ch >= ARRAY_SIZE(channel_name)))
+       if (ch >= ARRAY_SIZE(channel_name)) {
+               snd_BUG();
                return "PCM";
+       }
 
        return channel_name[ch];
 }
@@ -5405,6 +5407,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF),
        SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF),
        SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 5,1", ALC885_FIXUP_MACPRO_GPIO),
+       SND_PCI_QUIRK(0x106b, 0x4300, "iMac 9,1", ALC889_FIXUP_IMAC91_VREF),
        SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF),
        SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF),
        SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF),
@@ -5675,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[] = {
@@ -5682,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),
        {}
 };
 
@@ -5720,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 */
@@ -5821,7 +5841,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
        return alc_parse_auto_config(codec, alc269_ignore, ssids);
 }
 
-static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
+static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up)
 {
        int val = alc_read_coef_idx(codec, 0x04);
        if (power_up)
@@ -5838,10 +5858,10 @@ static void alc269_shutup(struct hda_codec *codec)
        if (spec->codec_variant != ALC269_TYPE_ALC269VB)
                return;
 
-       if ((alc_get_coef0(codec) & 0x00ff) == 0x017)
-               alc269_toggle_power_output(codec, 0);
-       if ((alc_get_coef0(codec) & 0x00ff) == 0x018) {
-               alc269_toggle_power_output(codec, 0);
+       if (spec->codec_variant == ALC269_TYPE_ALC269VB)
+               alc269vb_toggle_power_output(codec, 0);
+       if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
+                       (alc_get_coef0(codec) & 0x00ff) == 0x018) {
                msleep(150);
        }
 }
@@ -5851,24 +5871,22 @@ static int alc269_resume(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
-       if (spec->codec_variant == ALC269_TYPE_ALC269VB ||
+       if (spec->codec_variant == ALC269_TYPE_ALC269VB)
+               alc269vb_toggle_power_output(codec, 0);
+       if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
                        (alc_get_coef0(codec) & 0x00ff) == 0x018) {
-               alc269_toggle_power_output(codec, 0);
                msleep(150);
        }
 
        codec->patch_ops.init(codec);
 
-       if (spec->codec_variant == ALC269_TYPE_ALC269VB ||
+       if (spec->codec_variant == ALC269_TYPE_ALC269VB)
+               alc269vb_toggle_power_output(codec, 1);
+       if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
                        (alc_get_coef0(codec) & 0x00ff) == 0x017) {
-               alc269_toggle_power_output(codec, 1);
                msleep(200);
        }
 
-       if (spec->codec_variant == ALC269_TYPE_ALC269VB ||
-                       (alc_get_coef0(codec) & 0x00ff) == 0x018)
-               alc269_toggle_power_output(codec, 1);
-
        snd_hda_codec_resume_amp(codec);
        snd_hda_codec_resume_cache(codec);
        hda_call_check_power_status(codec, 0x01);
@@ -6186,6 +6204,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),
@@ -7046,6 +7065,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {
        { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 },
        { .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 },
        { .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 },
+       { .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 },
        { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
          .patch = patch_alc861 },
        { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
@@ -7059,6 +7079,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {
          .patch = patch_alc662 },
        { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
        { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
+       { .id = 0x10ec0668, .name = "ALC668", .patch = patch_alc662 },
        { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
        { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
        { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
@@ -7076,6 +7097,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {
        { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
        { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
        { .id = 0x10ec0899, .name = "ALC898", .patch = patch_alc882 },
+       { .id = 0x10ec0900, .name = "ALC1150", .patch = patch_alc882 },
        {} /* terminator */
 };
 
index 770013f..9ba8af0 100644 (file)
@@ -1763,6 +1763,8 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
                          "HP", STAC_HP_ZEPHYR),
        SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3660,
                          "HP Mini", STAC_92HD83XXX_HP_LED),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x144E,
+                         "HP Pavilion dv5", STAC_92HD83XXX_HP_INV_LED),
        {} /* terminator */
 };
 
index 72a2f60..019e1a0 100644 (file)
@@ -1809,11 +1809,11 @@ static int via_auto_fill_dac_nids(struct hda_codec *codec)
 {
        struct via_spec *spec = codec->spec;
        const struct auto_pin_cfg *cfg = &spec->autocfg;
-       int i, dac_num;
+       int i;
        hda_nid_t nid;
 
+       spec->multiout.num_dacs = 0;
        spec->multiout.dac_nids = spec->private_dac_nids;
-       dac_num = 0;
        for (i = 0; i < cfg->line_outs; i++) {
                hda_nid_t dac = 0;
                nid = cfg->line_out_pins[i];
@@ -1824,16 +1824,13 @@ static int via_auto_fill_dac_nids(struct hda_codec *codec)
                if (!i && parse_output_path(codec, nid, dac, 1,
                                            &spec->out_mix_path))
                        dac = spec->out_mix_path.path[0];
-               if (dac) {
-                       spec->private_dac_nids[i] = dac;
-                       dac_num++;
-               }
+               if (dac)
+                       spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
        }
        if (!spec->out_path[0].depth && spec->out_mix_path.depth) {
                spec->out_path[0] = spec->out_mix_path;
                spec->out_mix_path.depth = 0;
        }
-       spec->multiout.num_dacs = dac_num;
        return 0;
 }
 
@@ -3628,6 +3625,7 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
  */
 enum {
        VIA_FIXUP_INTMIC_BOOST,
+       VIA_FIXUP_ASUS_G75,
 };
 
 static void via_fixup_intmic_boost(struct hda_codec *codec,
@@ -3642,13 +3640,35 @@ static const struct hda_fixup via_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = via_fixup_intmic_boost,
        },
+       [VIA_FIXUP_ASUS_G75] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       /* set 0x24 and 0x33 as speakers */
+                       { 0x24, 0x991301f0 },
+                       { 0x33, 0x991301f1 }, /* subwoofer */
+                       { }
+               }
+       },
 };
 
 static const struct snd_pci_quirk vt2002p_fixups[] = {
+       SND_PCI_QUIRK(0x1043, 0x1487, "Asus G75", VIA_FIXUP_ASUS_G75),
        SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST),
        {}
 };
 
+/* NIDs 0x24 and 0x33 on VT1802 have connections to non-existing NID 0x3e
+ * Replace this with mixer NID 0x1c
+ */
+static void fix_vt1802_connections(struct hda_codec *codec)
+{
+       static hda_nid_t conn_24[] = { 0x14, 0x1c };
+       static hda_nid_t conn_33[] = { 0x1c };
+
+       snd_hda_override_conn_list(codec, 0x24, ARRAY_SIZE(conn_24), conn_24);
+       snd_hda_override_conn_list(codec, 0x33, ARRAY_SIZE(conn_33), conn_33);
+}
+
 /* patch for vt2002P */
 static int patch_vt2002P(struct hda_codec *codec)
 {
@@ -3663,6 +3683,8 @@ static int patch_vt2002P(struct hda_codec *codec)
        spec->aa_mix_nid = 0x21;
        override_mic_boost(codec, 0x2b, 0, 3, 40);
        override_mic_boost(codec, 0x29, 0, 3, 40);
+       if (spec->codec_type == VT1802)
+               fix_vt1802_connections(codec);
        add_secret_dac_path(codec);
 
        snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups);
index 3050a52..245d874 100644 (file)
@@ -2859,7 +2859,12 @@ static int snd_vt1724_resume(struct device *dev)
                ice->set_spdif_clock(ice, 0);
        } else {
                /* internal on-card clock */
-               snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1);
+               int rate;
+               if (ice->cur_rate)
+                       rate = ice->cur_rate;
+               else
+                       rate = ice->pro_rate_default;
+               snd_vt1724_set_pro_rate(ice, rate, 1);
        }
 
        update_spdif_bits(ice, ice->pm_saved_spdif_ctrl);
index b12308b..748e36c 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;
        }
@@ -3940,8 +3979,10 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
                case 8: /* SYNC IN */
                        val = hdspm_sync_in_sync_check(hdspm); break;
                default:
-                       val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
+                       val = hdspm_s1_sync_check(hdspm,
+                                       kcontrol->private_value-1);
                }
+               break;
 
        case AIO:
                switch (kcontrol->private_value) {
@@ -3954,6 +3995,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 +4008,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 +4026,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 +4471,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),
@@ -4855,7 +4900,7 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
                insel = "Coaxial";
                break;
        default:
-               insel = "Unkown";
+               insel = "Unknown";
        }
 
        snd_iprintf(buffer,
index bcbf1d0..99f32f7 100644 (file)
@@ -1,8 +1,9 @@
 snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o
 snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o
 
-snd-soc-dmaengine-pcm-objs := soc-dmaengine-pcm.o
-obj-$(CONFIG_SND_SOC_DMAENGINE_PCM) += snd-soc-dmaengine-pcm.o
+ifneq ($(CONFIG_SND_SOC_DMAENGINE_PCM),)
+snd-soc-core-objs += soc-dmaengine-pcm.o
+endif
 
 obj-$(CONFIG_SND_SOC)  += snd-soc-core.o
 obj-$(CONFIG_SND_SOC)  += codecs/
index c03b65a..054967d 100644 (file)
@@ -268,7 +268,7 @@ EXPORT_SYMBOL_GPL(arizona_out_ev);
 static unsigned int arizona_sysclk_48k_rates[] = {
        6144000,
        12288000,
-       22579200,
+       24576000,
        49152000,
        73728000,
        98304000,
@@ -278,7 +278,7 @@ static unsigned int arizona_sysclk_48k_rates[] = {
 static unsigned int arizona_sysclk_44k1_rates[] = {
        5644800,
        11289600,
-       24576000,
+       22579200,
        45158400,
        67737600,
        90316800,
index f994af3..e3f0a7f 100644 (file)
@@ -485,7 +485,7 @@ static int cs4271_probe(struct snd_soc_codec *codec)
                gpio_nreset = cs4271plat->gpio_nreset;
 
        if (gpio_nreset >= 0)
-               if (gpio_request(gpio_nreset, "CS4271 Reset"))
+               if (devm_gpio_request(codec->dev, gpio_nreset, "CS4271 Reset"))
                        gpio_nreset = -EINVAL;
        if (gpio_nreset >= 0) {
                /* Reset codec */
@@ -535,15 +535,10 @@ static int cs4271_probe(struct snd_soc_codec *codec)
 static int cs4271_remove(struct snd_soc_codec *codec)
 {
        struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
-       int gpio_nreset;
 
-       gpio_nreset = cs4271->gpio_nreset;
-
-       if (gpio_is_valid(gpio_nreset)) {
+       if (gpio_is_valid(cs4271->gpio_nreset))
                /* Set codec to the reset state */
-               gpio_set_value(gpio_nreset, 0);
-               gpio_free(gpio_nreset);
-       }
+               gpio_set_value(cs4271->gpio_nreset, 0);
 
        return 0;
 };
index 6159929..97a8105 100644 (file)
@@ -763,7 +763,7 @@ static int cs42l52_set_sysclk(struct snd_soc_dai *codec_dai,
        if ((freq >= CS42L52_MIN_CLK) && (freq <= CS42L52_MAX_CLK)) {
                cs42l52->sysclk = freq;
        } else {
-               dev_err(codec->dev, "Invalid freq paramter\n");
+               dev_err(codec->dev, "Invalid freq parameter\n");
                return -EINVAL;
        }
        return 0;
@@ -773,7 +773,6 @@ static int cs42l52_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
        struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
-       int ret = 0;
        u8 iface = 0;
 
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -822,7 +821,7 @@ static int cs42l52_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
        case SND_SOC_DAIFMT_NB_IF:
                break;
        default:
-               ret = -EINVAL;
+               return -EINVAL;
        }
        cs42l52->config.format = iface;
        snd_soc_write(codec, CS42L52_IFACE_CTL1, cs42l52->config.format);
index 185d8dd..f379b08 100644 (file)
 #define DA9055_AIF_WORD_S24_LE         (2 << 2)
 #define DA9055_AIF_WORD_S32_LE         (3 << 2)
 
+/* MIC_L_CTRL bit fields */
+#define DA9055_MIC_L_MUTE_EN           (1 << 6)
+
+/* MIC_R_CTRL bit fields */
+#define DA9055_MIC_R_MUTE_EN           (1 << 6)
+
 /* MIXIN_L_CTRL bit fields */
 #define DA9055_MIXIN_L_MIX_EN          (1 << 3)
 
@@ -476,7 +482,7 @@ static int da9055_put_alc_sw(struct snd_kcontrol *kcontrol,
                             struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       u8 reg_val, adc_left, adc_right;
+       u8 reg_val, adc_left, adc_right, mic_left, mic_right;
        int avg_left_data, avg_right_data, offset_l, offset_r;
 
        if (ucontrol->value.integer.value[0]) {
@@ -485,6 +491,16 @@ static int da9055_put_alc_sw(struct snd_kcontrol *kcontrol,
                 * offsets must be done first
                 */
 
+               /* Save current values from Mic control registers */
+               mic_left = snd_soc_read(codec, DA9055_MIC_L_CTRL);
+               mic_right = snd_soc_read(codec, DA9055_MIC_R_CTRL);
+
+               /* Mute Mic PGA Left and Right */
+               snd_soc_update_bits(codec, DA9055_MIC_L_CTRL,
+                                   DA9055_MIC_L_MUTE_EN, DA9055_MIC_L_MUTE_EN);
+               snd_soc_update_bits(codec, DA9055_MIC_R_CTRL,
+                                   DA9055_MIC_R_MUTE_EN, DA9055_MIC_R_MUTE_EN);
+
                /* Save current values from ADC control registers */
                adc_left = snd_soc_read(codec, DA9055_ADC_L_CTRL);
                adc_right = snd_soc_read(codec, DA9055_ADC_R_CTRL);
@@ -520,6 +536,10 @@ static int da9055_put_alc_sw(struct snd_kcontrol *kcontrol,
                /* Restore original values of ADC control registers */
                snd_soc_write(codec, DA9055_ADC_L_CTRL, adc_left);
                snd_soc_write(codec, DA9055_ADC_R_CTRL, adc_right);
+
+               /* Restore original values of Mic control registers */
+               snd_soc_write(codec, DA9055_MIC_L_CTRL, mic_left);
+               snd_soc_write(codec, DA9055_MIC_R_CTRL, mic_right);
        }
 
        return snd_soc_put_volsw(kcontrol, ucontrol);
index e8f97af..00b85cc 100644 (file)
@@ -820,10 +820,10 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"VIBRA DAC", NULL, "Vibra Playback"},
 
        /* ADC -> Stream mapping */
-       {"ADC Left", NULL, "Legacy Capture"},
-       {"ADC Left", NULL, "Capture"},
-       {"ADC Right", NULL, "Legacy Capture"},
-       {"ADC Right", NULL, "Capture"},
+       {"Legacy Capture" , NULL, "ADC Left"},
+       {"Capture", NULL, "ADC Left"},
+       {"Legacy Capture", NULL, "ADC Right"},
+       {"Capture" , NULL, "ADC Right"},
 
        /* Capture path */
        {"Analog Left Capture Route", "Headset Mic", "HSMIC"},
index efa93db..eab64a1 100644 (file)
@@ -1028,7 +1028,7 @@ SOC_DOUBLE_R_TLV("OUT2 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_2L,
                 WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_VOL_SHIFT, 0x9f, 0,
                 digital_tlv),
 SOC_DOUBLE("OUT2 Switch", WM2200_PDM_1, WM2200_SPK1L_MUTE_SHIFT,
-          WM2200_SPK1R_MUTE_SHIFT, 1, 0),
+          WM2200_SPK1R_MUTE_SHIFT, 1, 1),
 };
 
 WM2200_MIXER_ENUMS(OUT1L, WM2200_OUT1LMIX_INPUT_1_SOURCE);
@@ -2091,6 +2091,7 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
 
        switch (wm2200->rev) {
        case 0:
+       case 1:
                ret = regmap_register_patch(wm2200->regmap, wm2200_reva_patch,
                                            ARRAY_SIZE(wm2200_reva_patch));
                if (ret != 0) {
index 1722b58..7394e73 100644 (file)
@@ -42,6 +42,556 @@ static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
 static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
 static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0);
 
+static const struct reg_default wm5102_sysclk_reva_patch[] = {
+       { 0x3000, 0x2225 },
+       { 0x3001, 0x3a03 },
+       { 0x3002, 0x0225 },
+       { 0x3003, 0x0801 },
+       { 0x3004, 0x6249 },
+       { 0x3005, 0x0c04 },
+       { 0x3006, 0x0225 },
+       { 0x3007, 0x5901 },
+       { 0x3008, 0xe249 },
+       { 0x3009, 0x030d },
+       { 0x300a, 0x0249 },
+       { 0x300b, 0x2c01 },
+       { 0x300c, 0xe249 },
+       { 0x300d, 0x4342 },
+       { 0x300e, 0xe249 },
+       { 0x300f, 0x73c0 },
+       { 0x3010, 0x4249 },
+       { 0x3011, 0x0c00 },
+       { 0x3012, 0x0225 },
+       { 0x3013, 0x1f01 },
+       { 0x3014, 0x0225 },
+       { 0x3015, 0x1e01 },
+       { 0x3016, 0x0225 },
+       { 0x3017, 0xfa00 },
+       { 0x3018, 0x0000 },
+       { 0x3019, 0xf000 },
+       { 0x301a, 0x0000 },
+       { 0x301b, 0xf000 },
+       { 0x301c, 0x0000 },
+       { 0x301d, 0xf000 },
+       { 0x301e, 0x0000 },
+       { 0x301f, 0xf000 },
+       { 0x3020, 0x0000 },
+       { 0x3021, 0xf000 },
+       { 0x3022, 0x0000 },
+       { 0x3023, 0xf000 },
+       { 0x3024, 0x0000 },
+       { 0x3025, 0xf000 },
+       { 0x3026, 0x0000 },
+       { 0x3027, 0xf000 },
+       { 0x3028, 0x0000 },
+       { 0x3029, 0xf000 },
+       { 0x302a, 0x0000 },
+       { 0x302b, 0xf000 },
+       { 0x302c, 0x0000 },
+       { 0x302d, 0xf000 },
+       { 0x302e, 0x0000 },
+       { 0x302f, 0xf000 },
+       { 0x3030, 0x0225 },
+       { 0x3031, 0x1a01 },
+       { 0x3032, 0x0225 },
+       { 0x3033, 0x1e00 },
+       { 0x3034, 0x0225 },
+       { 0x3035, 0x1f00 },
+       { 0x3036, 0x6225 },
+       { 0x3037, 0xf800 },
+       { 0x3038, 0x0000 },
+       { 0x3039, 0xf000 },
+       { 0x303a, 0x0000 },
+       { 0x303b, 0xf000 },
+       { 0x303c, 0x0000 },
+       { 0x303d, 0xf000 },
+       { 0x303e, 0x0000 },
+       { 0x303f, 0xf000 },
+       { 0x3040, 0x2226 },
+       { 0x3041, 0x3a03 },
+       { 0x3042, 0x0226 },
+       { 0x3043, 0x0801 },
+       { 0x3044, 0x6249 },
+       { 0x3045, 0x0c06 },
+       { 0x3046, 0x0226 },
+       { 0x3047, 0x5901 },
+       { 0x3048, 0xe249 },
+       { 0x3049, 0x030d },
+       { 0x304a, 0x0249 },
+       { 0x304b, 0x2c01 },
+       { 0x304c, 0xe249 },
+       { 0x304d, 0x4342 },
+       { 0x304e, 0xe249 },
+       { 0x304f, 0x73c0 },
+       { 0x3050, 0x4249 },
+       { 0x3051, 0x0c00 },
+       { 0x3052, 0x0226 },
+       { 0x3053, 0x1f01 },
+       { 0x3054, 0x0226 },
+       { 0x3055, 0x1e01 },
+       { 0x3056, 0x0226 },
+       { 0x3057, 0xfa00 },
+       { 0x3058, 0x0000 },
+       { 0x3059, 0xf000 },
+       { 0x305a, 0x0000 },
+       { 0x305b, 0xf000 },
+       { 0x305c, 0x0000 },
+       { 0x305d, 0xf000 },
+       { 0x305e, 0x0000 },
+       { 0x305f, 0xf000 },
+       { 0x3060, 0x0000 },
+       { 0x3061, 0xf000 },
+       { 0x3062, 0x0000 },
+       { 0x3063, 0xf000 },
+       { 0x3064, 0x0000 },
+       { 0x3065, 0xf000 },
+       { 0x3066, 0x0000 },
+       { 0x3067, 0xf000 },
+       { 0x3068, 0x0000 },
+       { 0x3069, 0xf000 },
+       { 0x306a, 0x0000 },
+       { 0x306b, 0xf000 },
+       { 0x306c, 0x0000 },
+       { 0x306d, 0xf000 },
+       { 0x306e, 0x0000 },
+       { 0x306f, 0xf000 },
+       { 0x3070, 0x0226 },
+       { 0x3071, 0x1a01 },
+       { 0x3072, 0x0226 },
+       { 0x3073, 0x1e00 },
+       { 0x3074, 0x0226 },
+       { 0x3075, 0x1f00 },
+       { 0x3076, 0x6226 },
+       { 0x3077, 0xf800 },
+       { 0x3078, 0x0000 },
+       { 0x3079, 0xf000 },
+       { 0x307a, 0x0000 },
+       { 0x307b, 0xf000 },
+       { 0x307c, 0x0000 },
+       { 0x307d, 0xf000 },
+       { 0x307e, 0x0000 },
+       { 0x307f, 0xf000 },
+       { 0x3080, 0x2227 },
+       { 0x3081, 0x3a03 },
+       { 0x3082, 0x0227 },
+       { 0x3083, 0x0801 },
+       { 0x3084, 0x6255 },
+       { 0x3085, 0x0c04 },
+       { 0x3086, 0x0227 },
+       { 0x3087, 0x5901 },
+       { 0x3088, 0xe255 },
+       { 0x3089, 0x030d },
+       { 0x308a, 0x0255 },
+       { 0x308b, 0x2c01 },
+       { 0x308c, 0xe255 },
+       { 0x308d, 0x4342 },
+       { 0x308e, 0xe255 },
+       { 0x308f, 0x73c0 },
+       { 0x3090, 0x4255 },
+       { 0x3091, 0x0c00 },
+       { 0x3092, 0x0227 },
+       { 0x3093, 0x1f01 },
+       { 0x3094, 0x0227 },
+       { 0x3095, 0x1e01 },
+       { 0x3096, 0x0227 },
+       { 0x3097, 0xfa00 },
+       { 0x3098, 0x0000 },
+       { 0x3099, 0xf000 },
+       { 0x309a, 0x0000 },
+       { 0x309b, 0xf000 },
+       { 0x309c, 0x0000 },
+       { 0x309d, 0xf000 },
+       { 0x309e, 0x0000 },
+       { 0x309f, 0xf000 },
+       { 0x30a0, 0x0000 },
+       { 0x30a1, 0xf000 },
+       { 0x30a2, 0x0000 },
+       { 0x30a3, 0xf000 },
+       { 0x30a4, 0x0000 },
+       { 0x30a5, 0xf000 },
+       { 0x30a6, 0x0000 },
+       { 0x30a7, 0xf000 },
+       { 0x30a8, 0x0000 },
+       { 0x30a9, 0xf000 },
+       { 0x30aa, 0x0000 },
+       { 0x30ab, 0xf000 },
+       { 0x30ac, 0x0000 },
+       { 0x30ad, 0xf000 },
+       { 0x30ae, 0x0000 },
+       { 0x30af, 0xf000 },
+       { 0x30b0, 0x0227 },
+       { 0x30b1, 0x1a01 },
+       { 0x30b2, 0x0227 },
+       { 0x30b3, 0x1e00 },
+       { 0x30b4, 0x0227 },
+       { 0x30b5, 0x1f00 },
+       { 0x30b6, 0x6227 },
+       { 0x30b7, 0xf800 },
+       { 0x30b8, 0x0000 },
+       { 0x30b9, 0xf000 },
+       { 0x30ba, 0x0000 },
+       { 0x30bb, 0xf000 },
+       { 0x30bc, 0x0000 },
+       { 0x30bd, 0xf000 },
+       { 0x30be, 0x0000 },
+       { 0x30bf, 0xf000 },
+       { 0x30c0, 0x2228 },
+       { 0x30c1, 0x3a03 },
+       { 0x30c2, 0x0228 },
+       { 0x30c3, 0x0801 },
+       { 0x30c4, 0x6255 },
+       { 0x30c5, 0x0c06 },
+       { 0x30c6, 0x0228 },
+       { 0x30c7, 0x5901 },
+       { 0x30c8, 0xe255 },
+       { 0x30c9, 0x030d },
+       { 0x30ca, 0x0255 },
+       { 0x30cb, 0x2c01 },
+       { 0x30cc, 0xe255 },
+       { 0x30cd, 0x4342 },
+       { 0x30ce, 0xe255 },
+       { 0x30cf, 0x73c0 },
+       { 0x30d0, 0x4255 },
+       { 0x30d1, 0x0c00 },
+       { 0x30d2, 0x0228 },
+       { 0x30d3, 0x1f01 },
+       { 0x30d4, 0x0228 },
+       { 0x30d5, 0x1e01 },
+       { 0x30d6, 0x0228 },
+       { 0x30d7, 0xfa00 },
+       { 0x30d8, 0x0000 },
+       { 0x30d9, 0xf000 },
+       { 0x30da, 0x0000 },
+       { 0x30db, 0xf000 },
+       { 0x30dc, 0x0000 },
+       { 0x30dd, 0xf000 },
+       { 0x30de, 0x0000 },
+       { 0x30df, 0xf000 },
+       { 0x30e0, 0x0000 },
+       { 0x30e1, 0xf000 },
+       { 0x30e2, 0x0000 },
+       { 0x30e3, 0xf000 },
+       { 0x30e4, 0x0000 },
+       { 0x30e5, 0xf000 },
+       { 0x30e6, 0x0000 },
+       { 0x30e7, 0xf000 },
+       { 0x30e8, 0x0000 },
+       { 0x30e9, 0xf000 },
+       { 0x30ea, 0x0000 },
+       { 0x30eb, 0xf000 },
+       { 0x30ec, 0x0000 },
+       { 0x30ed, 0xf000 },
+       { 0x30ee, 0x0000 },
+       { 0x30ef, 0xf000 },
+       { 0x30f0, 0x0228 },
+       { 0x30f1, 0x1a01 },
+       { 0x30f2, 0x0228 },
+       { 0x30f3, 0x1e00 },
+       { 0x30f4, 0x0228 },
+       { 0x30f5, 0x1f00 },
+       { 0x30f6, 0x6228 },
+       { 0x30f7, 0xf800 },
+       { 0x30f8, 0x0000 },
+       { 0x30f9, 0xf000 },
+       { 0x30fa, 0x0000 },
+       { 0x30fb, 0xf000 },
+       { 0x30fc, 0x0000 },
+       { 0x30fd, 0xf000 },
+       { 0x30fe, 0x0000 },
+       { 0x30ff, 0xf000 },
+       { 0x3100, 0x222b },
+       { 0x3101, 0x3a03 },
+       { 0x3102, 0x222b },
+       { 0x3103, 0x5803 },
+       { 0x3104, 0xe26f },
+       { 0x3105, 0x030d },
+       { 0x3106, 0x626f },
+       { 0x3107, 0x2c01 },
+       { 0x3108, 0xe26f },
+       { 0x3109, 0x4342 },
+       { 0x310a, 0xe26f },
+       { 0x310b, 0x73c0 },
+       { 0x310c, 0x026f },
+       { 0x310d, 0x0c00 },
+       { 0x310e, 0x022b },
+       { 0x310f, 0x1f01 },
+       { 0x3110, 0x022b },
+       { 0x3111, 0x1e01 },
+       { 0x3112, 0x022b },
+       { 0x3113, 0xfa00 },
+       { 0x3114, 0x0000 },
+       { 0x3115, 0xf000 },
+       { 0x3116, 0x0000 },
+       { 0x3117, 0xf000 },
+       { 0x3118, 0x0000 },
+       { 0x3119, 0xf000 },
+       { 0x311a, 0x0000 },
+       { 0x311b, 0xf000 },
+       { 0x311c, 0x0000 },
+       { 0x311d, 0xf000 },
+       { 0x311e, 0x0000 },
+       { 0x311f, 0xf000 },
+       { 0x3120, 0x022b },
+       { 0x3121, 0x0a01 },
+       { 0x3122, 0x022b },
+       { 0x3123, 0x1e00 },
+       { 0x3124, 0x022b },
+       { 0x3125, 0x1f00 },
+       { 0x3126, 0x622b },
+       { 0x3127, 0xf800 },
+       { 0x3128, 0x0000 },
+       { 0x3129, 0xf000 },
+       { 0x312a, 0x0000 },
+       { 0x312b, 0xf000 },
+       { 0x312c, 0x0000 },
+       { 0x312d, 0xf000 },
+       { 0x312e, 0x0000 },
+       { 0x312f, 0xf000 },
+       { 0x3130, 0x0000 },
+       { 0x3131, 0xf000 },
+       { 0x3132, 0x0000 },
+       { 0x3133, 0xf000 },
+       { 0x3134, 0x0000 },
+       { 0x3135, 0xf000 },
+       { 0x3136, 0x0000 },
+       { 0x3137, 0xf000 },
+       { 0x3138, 0x0000 },
+       { 0x3139, 0xf000 },
+       { 0x313a, 0x0000 },
+       { 0x313b, 0xf000 },
+       { 0x313c, 0x0000 },
+       { 0x313d, 0xf000 },
+       { 0x313e, 0x0000 },
+       { 0x313f, 0xf000 },
+       { 0x3140, 0x0000 },
+       { 0x3141, 0xf000 },
+       { 0x3142, 0x0000 },
+       { 0x3143, 0xf000 },
+       { 0x3144, 0x0000 },
+       { 0x3145, 0xf000 },
+       { 0x3146, 0x0000 },
+       { 0x3147, 0xf000 },
+       { 0x3148, 0x0000 },
+       { 0x3149, 0xf000 },
+       { 0x314a, 0x0000 },
+       { 0x314b, 0xf000 },
+       { 0x314c, 0x0000 },
+       { 0x314d, 0xf000 },
+       { 0x314e, 0x0000 },
+       { 0x314f, 0xf000 },
+       { 0x3150, 0x0000 },
+       { 0x3151, 0xf000 },
+       { 0x3152, 0x0000 },
+       { 0x3153, 0xf000 },
+       { 0x3154, 0x0000 },
+       { 0x3155, 0xf000 },
+       { 0x3156, 0x0000 },
+       { 0x3157, 0xf000 },
+       { 0x3158, 0x0000 },
+       { 0x3159, 0xf000 },
+       { 0x315a, 0x0000 },
+       { 0x315b, 0xf000 },
+       { 0x315c, 0x0000 },
+       { 0x315d, 0xf000 },
+       { 0x315e, 0x0000 },
+       { 0x315f, 0xf000 },
+       { 0x3160, 0x0000 },
+       { 0x3161, 0xf000 },
+       { 0x3162, 0x0000 },
+       { 0x3163, 0xf000 },
+       { 0x3164, 0x0000 },
+       { 0x3165, 0xf000 },
+       { 0x3166, 0x0000 },
+       { 0x3167, 0xf000 },
+       { 0x3168, 0x0000 },
+       { 0x3169, 0xf000 },
+       { 0x316a, 0x0000 },
+       { 0x316b, 0xf000 },
+       { 0x316c, 0x0000 },
+       { 0x316d, 0xf000 },
+       { 0x316e, 0x0000 },
+       { 0x316f, 0xf000 },
+       { 0x3170, 0x0000 },
+       { 0x3171, 0xf000 },
+       { 0x3172, 0x0000 },
+       { 0x3173, 0xf000 },
+       { 0x3174, 0x0000 },
+       { 0x3175, 0xf000 },
+       { 0x3176, 0x0000 },
+       { 0x3177, 0xf000 },
+       { 0x3178, 0x0000 },
+       { 0x3179, 0xf000 },
+       { 0x317a, 0x0000 },
+       { 0x317b, 0xf000 },
+       { 0x317c, 0x0000 },
+       { 0x317d, 0xf000 },
+       { 0x317e, 0x0000 },
+       { 0x317f, 0xf000 },
+       { 0x3180, 0x2001 },
+       { 0x3181, 0xf101 },
+       { 0x3182, 0x0000 },
+       { 0x3183, 0xf000 },
+       { 0x3184, 0x0000 },
+       { 0x3185, 0xf000 },
+       { 0x3186, 0x0000 },
+       { 0x3187, 0xf000 },
+       { 0x3188, 0x0000 },
+       { 0x3189, 0xf000 },
+       { 0x318a, 0x0000 },
+       { 0x318b, 0xf000 },
+       { 0x318c, 0x0000 },
+       { 0x318d, 0xf000 },
+       { 0x318e, 0x0000 },
+       { 0x318f, 0xf000 },
+       { 0x3190, 0x0000 },
+       { 0x3191, 0xf000 },
+       { 0x3192, 0x0000 },
+       { 0x3193, 0xf000 },
+       { 0x3194, 0x0000 },
+       { 0x3195, 0xf000 },
+       { 0x3196, 0x0000 },
+       { 0x3197, 0xf000 },
+       { 0x3198, 0x0000 },
+       { 0x3199, 0xf000 },
+       { 0x319a, 0x0000 },
+       { 0x319b, 0xf000 },
+       { 0x319c, 0x0000 },
+       { 0x319d, 0xf000 },
+       { 0x319e, 0x0000 },
+       { 0x319f, 0xf000 },
+       { 0x31a0, 0x0000 },
+       { 0x31a1, 0xf000 },
+       { 0x31a2, 0x0000 },
+       { 0x31a3, 0xf000 },
+       { 0x31a4, 0x0000 },
+       { 0x31a5, 0xf000 },
+       { 0x31a6, 0x0000 },
+       { 0x31a7, 0xf000 },
+       { 0x31a8, 0x0000 },
+       { 0x31a9, 0xf000 },
+       { 0x31aa, 0x0000 },
+       { 0x31ab, 0xf000 },
+       { 0x31ac, 0x0000 },
+       { 0x31ad, 0xf000 },
+       { 0x31ae, 0x0000 },
+       { 0x31af, 0xf000 },
+       { 0x31b0, 0x0000 },
+       { 0x31b1, 0xf000 },
+       { 0x31b2, 0x0000 },
+       { 0x31b3, 0xf000 },
+       { 0x31b4, 0x0000 },
+       { 0x31b5, 0xf000 },
+       { 0x31b6, 0x0000 },
+       { 0x31b7, 0xf000 },
+       { 0x31b8, 0x0000 },
+       { 0x31b9, 0xf000 },
+       { 0x31ba, 0x0000 },
+       { 0x31bb, 0xf000 },
+       { 0x31bc, 0x0000 },
+       { 0x31bd, 0xf000 },
+       { 0x31be, 0x0000 },
+       { 0x31bf, 0xf000 },
+       { 0x31c0, 0x0000 },
+       { 0x31c1, 0xf000 },
+       { 0x31c2, 0x0000 },
+       { 0x31c3, 0xf000 },
+       { 0x31c4, 0x0000 },
+       { 0x31c5, 0xf000 },
+       { 0x31c6, 0x0000 },
+       { 0x31c7, 0xf000 },
+       { 0x31c8, 0x0000 },
+       { 0x31c9, 0xf000 },
+       { 0x31ca, 0x0000 },
+       { 0x31cb, 0xf000 },
+       { 0x31cc, 0x0000 },
+       { 0x31cd, 0xf000 },
+       { 0x31ce, 0x0000 },
+       { 0x31cf, 0xf000 },
+       { 0x31d0, 0x0000 },
+       { 0x31d1, 0xf000 },
+       { 0x31d2, 0x0000 },
+       { 0x31d3, 0xf000 },
+       { 0x31d4, 0x0000 },
+       { 0x31d5, 0xf000 },
+       { 0x31d6, 0x0000 },
+       { 0x31d7, 0xf000 },
+       { 0x31d8, 0x0000 },
+       { 0x31d9, 0xf000 },
+       { 0x31da, 0x0000 },
+       { 0x31db, 0xf000 },
+       { 0x31dc, 0x0000 },
+       { 0x31dd, 0xf000 },
+       { 0x31de, 0x0000 },
+       { 0x31df, 0xf000 },
+       { 0x31e0, 0x0000 },
+       { 0x31e1, 0xf000 },
+       { 0x31e2, 0x0000 },
+       { 0x31e3, 0xf000 },
+       { 0x31e4, 0x0000 },
+       { 0x31e5, 0xf000 },
+       { 0x31e6, 0x0000 },
+       { 0x31e7, 0xf000 },
+       { 0x31e8, 0x0000 },
+       { 0x31e9, 0xf000 },
+       { 0x31ea, 0x0000 },
+       { 0x31eb, 0xf000 },
+       { 0x31ec, 0x0000 },
+       { 0x31ed, 0xf000 },
+       { 0x31ee, 0x0000 },
+       { 0x31ef, 0xf000 },
+       { 0x31f0, 0x0000 },
+       { 0x31f1, 0xf000 },
+       { 0x31f2, 0x0000 },
+       { 0x31f3, 0xf000 },
+       { 0x31f4, 0x0000 },
+       { 0x31f5, 0xf000 },
+       { 0x31f6, 0x0000 },
+       { 0x31f7, 0xf000 },
+       { 0x31f8, 0x0000 },
+       { 0x31f9, 0xf000 },
+       { 0x31fa, 0x0000 },
+       { 0x31fb, 0xf000 },
+       { 0x31fc, 0x0000 },
+       { 0x31fd, 0xf000 },
+       { 0x31fe, 0x0000 },
+       { 0x31ff, 0xf000 },
+       { 0x024d, 0xff50 },
+       { 0x0252, 0xff50 },
+       { 0x0259, 0x0112 },
+       { 0x025e, 0x0112 },
+};
+
+static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w,
+                           struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct arizona *arizona = dev_get_drvdata(codec->dev);
+       struct regmap *regmap = codec->control_data;
+       const struct reg_default *patch = NULL;
+       int i, patch_size;
+
+       switch (arizona->rev) {
+       case 0:
+               patch = wm5102_sysclk_reva_patch;
+               patch_size = ARRAY_SIZE(wm5102_sysclk_reva_patch);
+               break;
+       }
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               if (patch)
+                       for (i = 0; i < patch_size; i++)
+                               regmap_write(regmap, patch[i].reg,
+                                            patch[i].def);
+               break;
+
+       default:
+               break;
+       }
+
+       return 0;
+}
+
 static const struct snd_kcontrol_new wm5102_snd_controls[] = {
 SOC_SINGLE("IN1 High Performance Switch", ARIZONA_IN1L_CONTROL,
           ARIZONA_IN1_OSR_SHIFT, 1, 0),
@@ -297,7 +847,7 @@ static const struct snd_kcontrol_new wm5102_aec_loopback_mux =
 
 static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = {
 SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT,
-                   0, NULL, 0),
+                   0, wm5102_sysclk_ev, SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1,
                    ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK,
index 5421fd9..4c0a8e4 100644 (file)
@@ -782,7 +782,7 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream,
                wm8978->mclk_idx = -1;
                f_sel = wm8978->f_mclk;
        } else {
-               if (!wm8978->f_pllout) {
+               if (!wm8978->f_opclk) {
                        /* We only enter here, if OPCLK is not used */
                        int ret = wm8978_configure_pll(codec);
                        if (ret < 0)
index 2b2dadc..b2b2b37 100644 (file)
@@ -1045,6 +1045,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 +1064,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 +2692,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 +2713,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))
@@ -3706,7 +3722,7 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
        } while (count--);
 
        if (count == 0)
-               dev_warn(codec->dev, "No impedence range reported for jack\n");
+               dev_warn(codec->dev, "No impedance range reported for jack\n");
 
 #ifndef CONFIG_SND_SOC_WM8994_MODULE
        trace_snd_soc_jack_irq(dev_name(codec->dev));
index f142ec1..ccbce57 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;
index b9f1659..2ba0814 100644 (file)
@@ -71,7 +71,6 @@ static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id)
                printk(KERN_WARNING "%s: got err interrupt 0x%lx\n",
                                __func__, cause);
                writel(cause, priv->io + KIRKWOOD_ERR_CAUSE);
-               return IRQ_HANDLED;
        }
 
        /* we've enabled only bytes interrupts ... */
@@ -178,7 +177,7 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
        }
 
        dram = mv_mbus_dram_info();
-       addr = virt_to_phys(substream->dma_buffer.area);
+       addr = substream->dma_buffer.addr;
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                prdata->play_stream = substream;
                kirkwood_dma_conf_mbus_windows(priv->io,
index 542538d..1d5db48 100644 (file)
@@ -95,7 +95,7 @@ static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate)
        do {
                cpu_relax();
                value = readl(io + KIRKWOOD_DCO_SPCR_STATUS);
-               value &= KIRKWOOD_DCO_SPCR_STATUS;
+               value &= KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK;
        } while (value == 0);
 }
 
@@ -180,67 +180,72 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
                                int cmd, struct snd_soc_dai *dai)
 {
        struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
-       unsigned long value;
-
-       /*
-        * specs says KIRKWOOD_PLAYCTL must be read 2 times before
-        * changing it. So read 1 time here and 1 later.
-        */
-       value = readl(priv->io + KIRKWOOD_PLAYCTL);
+       uint32_t ctl, value;
+
+       ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
+       if (ctl & KIRKWOOD_PLAYCTL_PAUSE) {
+               unsigned timeout = 5000;
+               /*
+                * The Armada510 spec says that if we enter pause mode, the
+                * busy bit must be read back as clear _twice_.  Make sure
+                * we respect that otherwise we get DMA underruns.
+                */
+               do {
+                       value = ctl;
+                       ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
+                       if (!((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY))
+                               break;
+                       udelay(1);
+               } while (timeout--);
+
+               if ((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY)
+                       dev_notice(dai->dev, "timed out waiting for busy to deassert: %08x\n",
+                                  ctl);
+       }
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
-               /* stop audio, enable interrupts */
-               value = readl(priv->io + KIRKWOOD_PLAYCTL);
-               value |= KIRKWOOD_PLAYCTL_PAUSE;
-               writel(value, priv->io + KIRKWOOD_PLAYCTL);
-
                value = readl(priv->io + KIRKWOOD_INT_MASK);
                value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
                writel(value, priv->io + KIRKWOOD_INT_MASK);
 
                /* configure audio & enable i2s playback */
-               value = readl(priv->io + KIRKWOOD_PLAYCTL);
-               value &= ~KIRKWOOD_PLAYCTL_BURST_MASK;
-               value &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE
+               ctl &= ~KIRKWOOD_PLAYCTL_BURST_MASK;
+               ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE
                                | KIRKWOOD_PLAYCTL_SPDIF_EN);
 
                if (priv->burst == 32)
-                       value |= KIRKWOOD_PLAYCTL_BURST_32;
+                       ctl |= KIRKWOOD_PLAYCTL_BURST_32;
                else
-                       value |= KIRKWOOD_PLAYCTL_BURST_128;
-               value |= KIRKWOOD_PLAYCTL_I2S_EN;
-               writel(value, priv->io + KIRKWOOD_PLAYCTL);
+                       ctl |= KIRKWOOD_PLAYCTL_BURST_128;
+               ctl |= KIRKWOOD_PLAYCTL_I2S_EN;
+               writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
                break;
 
        case SNDRV_PCM_TRIGGER_STOP:
                /* stop audio, disable interrupts */
-               value = readl(priv->io + KIRKWOOD_PLAYCTL);
-               value |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
-               writel(value, priv->io + KIRKWOOD_PLAYCTL);
+               ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
+               writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
 
                value = readl(priv->io + KIRKWOOD_INT_MASK);
                value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES;
                writel(value, priv->io + KIRKWOOD_INT_MASK);
 
                /* disable all playbacks */
-               value = readl(priv->io + KIRKWOOD_PLAYCTL);
-               value &= ~(KIRKWOOD_PLAYCTL_I2S_EN | KIRKWOOD_PLAYCTL_SPDIF_EN);
-               writel(value, priv->io + KIRKWOOD_PLAYCTL);
+               ctl &= ~(KIRKWOOD_PLAYCTL_I2S_EN | KIRKWOOD_PLAYCTL_SPDIF_EN);
+               writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
                break;
 
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
        case SNDRV_PCM_TRIGGER_SUSPEND:
-               value = readl(priv->io + KIRKWOOD_PLAYCTL);
-               value |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
-               writel(value, priv->io + KIRKWOOD_PLAYCTL);
+               ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
+               writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
                break;
 
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               value = readl(priv->io + KIRKWOOD_PLAYCTL);
-               value &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE);
-               writel(value, priv->io + KIRKWOOD_PLAYCTL);
+               ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE);
+               writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
                break;
 
        default:
@@ -260,11 +265,6 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
-               /* stop audio, enable interrupts */
-               value = readl(priv->io + KIRKWOOD_RECCTL);
-               value |= KIRKWOOD_RECCTL_PAUSE;
-               writel(value, priv->io + KIRKWOOD_RECCTL);
-
                value = readl(priv->io + KIRKWOOD_INT_MASK);
                value |= KIRKWOOD_INT_CAUSE_REC_BYTES;
                writel(value, priv->io + KIRKWOOD_INT_MASK);
index aa037b2..c294fbb 100644 (file)
@@ -523,16 +523,24 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
 
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                        /*
-                        * write a data to saif data register to trigger
-                        * the transfer
+                        * write data to saif data register to trigger
+                        * the transfer.
+                        * For 24-bit format the 32-bit FIFO register stores
+                        * only one channel, so we need to write twice.
+                        * This is also safe for the other non 24-bit formats.
                         */
                        __raw_writel(0, saif->base + SAIF_DATA);
+                       __raw_writel(0, saif->base + SAIF_DATA);
                } else {
                        /*
-                        * read a data from saif data register to trigger
-                        * the receive
+                        * read data from saif data register to trigger
+                        * the receive.
+                        * For 24-bit format the 32-bit FIFO register stores
+                        * only one channel, so we need to read twice.
+                        * This is also safe for the other non 24-bit formats.
                         */
                        __raw_readl(saif->base + SAIF_DATA);
+                       __raw_readl(saif->base + SAIF_DATA);
                }
 
                master_saif->ongoing = 1;
@@ -812,3 +820,4 @@ module_platform_driver(mxs_saif_driver);
 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
 MODULE_DESCRIPTION("MXS ASoC SAIF driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mxs-saif");
index dc0ee76..d8e96b2 100644 (file)
@@ -575,56 +575,53 @@ static struct snd_soc_card ams_delta_audio_card = {
 };
 
 /* Module init/exit */
-static struct platform_device *ams_delta_audio_platform_device;
-static struct platform_device *cx20442_platform_device;
-
-static int __init ams_delta_module_init(void)
+static __devinit int ams_delta_probe(struct platform_device *pdev)
 {
+       struct snd_soc_card *card = &ams_delta_audio_card;
        int ret;
 
-       if (!(machine_is_ams_delta()))
-               return -ENODEV;
-
-       ams_delta_audio_platform_device =
-                       platform_device_alloc("soc-audio", -1);
-       if (!ams_delta_audio_platform_device)
-               return -ENOMEM;
+       card->dev = &pdev->dev;
 
-       platform_set_drvdata(ams_delta_audio_platform_device,
-                               &ams_delta_audio_card);
-
-       ret = platform_device_add(ams_delta_audio_platform_device);
-       if (ret)
-               goto err;
-
-       /*
-        * Codec platform device could be registered from elsewhere (board?),
-        * but I do it here as it makes sense only if used with the card.
-        */
-       cx20442_platform_device =
-               platform_device_register_simple("cx20442-codec", -1, NULL, 0);
+       ret = snd_soc_register_card(card);
+       if (ret) {
+               dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
+               card->dev = NULL;
+               return ret;
+       }
        return 0;
-err:
-       platform_device_put(ams_delta_audio_platform_device);
-       return ret;
 }
-late_initcall(ams_delta_module_init);
 
-static void __exit ams_delta_module_exit(void)
+static int __devexit ams_delta_remove(struct platform_device *pdev)
 {
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+
        if (tty_unregister_ldisc(N_V253) != 0)
-               dev_warn(&ams_delta_audio_platform_device->dev,
+               dev_warn(&pdev->dev,
                        "failed to unregister V253 line discipline\n");
 
        snd_soc_jack_free_gpios(&ams_delta_hook_switch,
                        ARRAY_SIZE(ams_delta_hook_switch_gpios),
                        ams_delta_hook_switch_gpios);
 
-       platform_device_unregister(cx20442_platform_device);
-       platform_device_unregister(ams_delta_audio_platform_device);
+       snd_soc_unregister_card(card);
+       card->dev = NULL;
+       return 0;
 }
-module_exit(ams_delta_module_exit);
+
+#define DRV_NAME "ams-delta-audio"
+
+static struct platform_driver ams_delta_driver = {
+       .driver = {
+               .name = DRV_NAME,
+               .owner = THIS_MODULE,
+       },
+       .probe = ams_delta_probe,
+       .remove = __devexit_p(ams_delta_remove),
+};
+
+module_platform_driver(ams_delta_driver);
 
 MODULE_AUTHOR("Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>");
 MODULE_DESCRIPTION("ALSA SoC driver for Amstrad E3 (Delta) videophone");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
index 4a73ef3..a57a4e6 100644 (file)
@@ -216,7 +216,7 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd)
        twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk");
        twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk");
        twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out");
-       twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator");
+       twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vibrator");
        twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic");
        twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic");
        twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic");
index 68f2cd1..5a6aeaf 100644 (file)
@@ -464,9 +464,9 @@ static __devinit int asoc_dmic_probe(struct platform_device *pdev)
 
        mutex_init(&dmic->mutex);
 
-       dmic->fclk = clk_get(dmic->dev, "dmic_fck");
+       dmic->fclk = clk_get(dmic->dev, "fck");
        if (IS_ERR(dmic->fclk)) {
-               dev_err(dmic->dev, "cant get dmic_fck\n");
+               dev_err(dmic->dev, "cant get fck\n");
                return -ENODEV;
        }
 
index c02b001..56965bb 100644 (file)
@@ -40,7 +40,6 @@
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 
-#include <plat/omap_hwmod.h>
 #include "omap-mcpdm.h"
 #include "omap-pcm.h"
 
@@ -260,13 +259,9 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
        mutex_lock(&mcpdm->mutex);
 
        if (!dai->active) {
-               /* Enable watch dog for ES above ES 1.0 to avoid saturation */
-               if (omap_rev() != OMAP4430_REV_ES1_0) {
-                       u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
+               u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
 
-                       omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL,
-                                        ctrl | MCPDM_WD_EN);
-               }
+               omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl | MCPDM_WD_EN);
                omap_mcpdm_open_streams(mcpdm);
        }
        mutex_unlock(&mcpdm->mutex);
index 677b567..1ff6bb9 100644 (file)
 
 #include <linux/clk.h>
 #include <linux/platform_device.h>
+#include <linux/gpio.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
 
 #include <asm/mach-types.h>
-#include <mach/hardware.h>
-#include <mach/gpio.h>
-#include <mach/board-zoom.h>
 #include <linux/platform_data/asoc-ti-mcbsp.h>
+#include <linux/platform_data/gpio-omap.h>
 
 /* Register descriptions for twl4030 codec part */
 #include <linux/mfd/twl4030-audio.h>
index 73ac546..e834faf 100644 (file)
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
+#include <linux/platform_data/dma-mmp_tdma.h>
 #include <linux/platform_data/mmp_audio.h>
 #include <sound/pxa2xx-lib.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
-#include <mach/sram.h>
 #include <sound/dmaengine_pcm.h>
 
 struct mmp_dma_data {
index e7b8317..3c7c3a5 100644 (file)
@@ -207,6 +207,8 @@ config SND_SOC_BELLS
        select SND_SOC_WM5102
        select SND_SOC_WM5110
        select SND_SOC_WM9081
+       select SND_SOC_WM0010
+       select SND_SOC_WM1250_EV1
 
 config SND_SOC_LOWLAND
        tristate "Audio support for Wolfson Lowland"
index 5dc10df..a2ca156 100644 (file)
@@ -247,7 +247,7 @@ static struct snd_soc_dai_link bells_dai_wm5110[] = {
        {
                .name = "Sub",
                .stream_name = "Sub",
-               .cpu_dai_name = "wm5102-aif3",
+               .cpu_dai_name = "wm5110-aif3",
                .codec_dai_name = "wm9081-hifi",
                .codec_name = "wm9081.1-006c",
                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
index 5328ae5..9d7f307 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/sh_dma.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/workqueue.h>
 #include <sound/soc.h>
 #include <sound/sh_fsi.h>
 
@@ -223,7 +224,7 @@ struct fsi_stream {
         */
        struct dma_chan         *chan;
        struct sh_dmae_slave    slave; /* see fsi_handler_init() */
-       struct tasklet_struct   tasklet;
+       struct work_struct      work;
        dma_addr_t              dma;
 };
 
@@ -1085,9 +1086,9 @@ static void fsi_dma_complete(void *data)
        snd_pcm_period_elapsed(io->substream);
 }
 
-static void fsi_dma_do_tasklet(unsigned long data)
+static void fsi_dma_do_work(struct work_struct *work)
 {
-       struct fsi_stream *io = (struct fsi_stream *)data;
+       struct fsi_stream *io = container_of(work, struct fsi_stream, work);
        struct fsi_priv *fsi = fsi_stream_to_priv(io);
        struct snd_soc_dai *dai;
        struct dma_async_tx_descriptor *desc;
@@ -1129,7 +1130,7 @@ static void fsi_dma_do_tasklet(unsigned long data)
         * FIXME
         *
         * In DMAEngine case, codec and FSI cannot be started simultaneously
-        * since FSI is using tasklet.
+        * since FSI is using the scheduler work queue.
         * Therefore, in capture case, probably FSI FIFO will have got
         * overflow error in this point.
         * in that case, DMA cannot start transfer until error was cleared.
@@ -1153,7 +1154,7 @@ static bool fsi_dma_filter(struct dma_chan *chan, void *param)
 
 static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io)
 {
-       tasklet_schedule(&io->tasklet);
+       schedule_work(&io->work);
 
        return 0;
 }
@@ -1195,14 +1196,14 @@ static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct dev
                return fsi_stream_probe(fsi, dev);
        }
 
-       tasklet_init(&io->tasklet, fsi_dma_do_tasklet, (unsigned long)io);
+       INIT_WORK(&io->work, fsi_dma_do_work);
 
        return 0;
 }
 
 static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io)
 {
-       tasklet_kill(&io->tasklet);
+       cancel_work_sync(&io->work);
 
        fsi_stream_stop(fsi, io);
 
index d119862..10d21be 100644 (file)
@@ -2786,8 +2786,9 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
        val = (ucontrol->value.integer.value[0] + min) & mask;
        val = val << shift;
 
-       if (snd_soc_update_bits_locked(codec, reg, val_mask, val))
-                       return err;
+       err = snd_soc_update_bits_locked(codec, reg, val_mask, val);
+       if (err < 0)
+               return err;
 
        if (snd_soc_volsw_is_stereo(mc)) {
                val_mask = mask << rshift;
index d0a4be3..6e35bca 100644 (file)
@@ -3745,7 +3745,7 @@ void snd_soc_dapm_shutdown(struct snd_soc_card *card)
 {
        struct snd_soc_codec *codec;
 
-       list_for_each_entry(codec, &card->codec_dev_list, list) {
+       list_for_each_entry(codec, &card->codec_dev_list, card_list) {
                soc_dapm_shutdown_codec(&codec->dapm);
                if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY)
                        snd_soc_dapm_set_bias_level(&codec->dapm,
index fa0fd8d..1ab5fe0 100644 (file)
@@ -22,7 +22,7 @@
 
 /**
  * snd_soc_jack_new - Create a new jack
- * @card:  ASoC card
+ * @codec: ASoC codec
  * @id:    an identifying string for this jack
  * @type:  a bitmask of enum snd_jack_type values that can be detected by
  *         this jack
@@ -133,12 +133,13 @@ EXPORT_SYMBOL_GPL(snd_soc_jack_add_zones);
 
 /**
  * snd_soc_jack_get_type - Based on the mic bias value, this function returns
- * the type of jack from the zones delcared in the jack type
+ * the type of jack from the zones declared in the jack type
  *
+ * @jack:  ASoC jack
  * @micbias_voltage:  mic bias voltage at adc channel when jack is plugged in
  *
  * Based on the mic bias value passed, this function helps identify
- * the type of jack from the already delcared jack zones
+ * the type of jack from the already declared jack zones
  */
 int snd_soc_jack_get_type(struct snd_soc_jack *jack, int micbias_voltage)
 {
index 356611d..54f7e25 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 b7c996e..a26c6bf 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 561bb74..dbf7999 100644 (file)
@@ -339,7 +339,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
        }
 
        mutex_init(&chip->mutex);
-       mutex_init(&chip->shutdown_mutex);
+       init_rwsem(&chip->shutdown_rwsem);
        chip->index = idx;
        chip->dev = dev;
        chip->card = card;
@@ -559,9 +559,11 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
                return;
 
        card = chip->card;
-       mutex_lock(&register_mutex);
-       mutex_lock(&chip->shutdown_mutex);
+       down_write(&chip->shutdown_rwsem);
        chip->shutdown = 1;
+       up_write(&chip->shutdown_rwsem);
+
+       mutex_lock(&register_mutex);
        chip->num_interfaces--;
        if (chip->num_interfaces <= 0) {
                snd_card_disconnect(card);
@@ -582,11 +584,9 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
                        snd_usb_mixer_disconnect(p);
                }
                usb_chip[chip->index] = NULL;
-               mutex_unlock(&chip->shutdown_mutex);
                mutex_unlock(&register_mutex);
                snd_card_free_when_closed(card);
        } else {
-               mutex_unlock(&chip->shutdown_mutex);
                mutex_unlock(&register_mutex);
        }
 }
@@ -618,16 +618,20 @@ int snd_usb_autoresume(struct snd_usb_audio *chip)
 {
        int err = -ENODEV;
 
+       down_read(&chip->shutdown_rwsem);
        if (!chip->shutdown && !chip->probing)
                err = usb_autopm_get_interface(chip->pm_intf);
+       up_read(&chip->shutdown_rwsem);
 
        return err;
 }
 
 void snd_usb_autosuspend(struct snd_usb_audio *chip)
 {
+       down_read(&chip->shutdown_rwsem);
        if (!chip->shutdown && !chip->probing)
                usb_autopm_put_interface(chip->pm_intf);
+       up_read(&chip->shutdown_rwsem);
 }
 
 static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
index afa4f9e..814cb35 100644 (file)
@@ -126,6 +126,7 @@ struct snd_usb_substream {
        struct snd_usb_endpoint *sync_endpoint;
        unsigned long flags;
        bool need_setup_ep;             /* (re)configure EP at prepare? */
+       unsigned int speed;             /* USB_SPEED_XXX */
 
        u64 formats;                    /* format bitmasks (all or'ed) */
        unsigned int num_formats;               /* number of supported audio formats (list) */
index 7f78c6d..34de6f2 100644 (file)
@@ -35,6 +35,7 @@
 
 #define EP_FLAG_ACTIVATED      0
 #define EP_FLAG_RUNNING                1
+#define EP_FLAG_STOPPING       2
 
 /*
  * snd_usb_endpoint is a model that abstracts everything related to an
@@ -502,10 +503,20 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep)
        if (alive)
                snd_printk(KERN_ERR "timeout: still %d active urbs on EP #%x\n",
                                        alive, ep->ep_num);
+       clear_bit(EP_FLAG_STOPPING, &ep->flags);
 
        return 0;
 }
 
+/* sync the pending stop operation;
+ * this function itself doesn't trigger the stop operation
+ */
+void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep)
+{
+       if (ep && test_bit(EP_FLAG_STOPPING, &ep->flags))
+               wait_clear_urbs(ep);
+}
+
 /*
  * unlink active urbs.
  */
@@ -918,6 +929,8 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
 
                if (wait)
                        wait_clear_urbs(ep);
+               else
+                       set_bit(EP_FLAG_STOPPING, &ep->flags);
        }
 }
 
index 6376ccf..3d4c970 100644 (file)
@@ -19,6 +19,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
 int  snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep);
 void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
                           int force, int can_sleep, int wait);
+void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep);
 int  snd_usb_endpoint_activate(struct snd_usb_endpoint *ep);
 int  snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep);
 void snd_usb_endpoint_free(struct list_head *head);
index c83f614..eeefbce 100644 (file)
@@ -148,6 +148,7 @@ struct snd_usb_midi_out_endpoint {
                struct snd_usb_midi_out_endpoint* ep;
                struct snd_rawmidi_substream *substream;
                int active;
+               bool autopm_reference;
                uint8_t cable;          /* cable number << 4 */
                uint8_t state;
 #define STATE_UNKNOWN  0
@@ -1076,7 +1077,8 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
                return -ENXIO;
        }
        err = usb_autopm_get_interface(umidi->iface);
-       if (err < 0)
+       port->autopm_reference = err >= 0;
+       if (err < 0 && err != -EACCES)
                return -EIO;
        substream->runtime->private_data = port;
        port->state = STATE_UNKNOWN;
@@ -1087,9 +1089,11 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
 static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream)
 {
        struct snd_usb_midi* umidi = substream->rmidi->private_data;
+       struct usbmidi_out_port *port = substream->runtime->private_data;
 
        substream_open(substream, 0);
-       usb_autopm_put_interface(umidi->iface);
+       if (port->autopm_reference)
+               usb_autopm_put_interface(umidi->iface);
        return 0;
 }
 
index fe56c9d..298070e 100644 (file)
@@ -287,25 +287,32 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
        unsigned char buf[2];
        int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
        int timeout = 10;
-       int err;
+       int idx = 0, err;
 
        err = snd_usb_autoresume(cval->mixer->chip);
        if (err < 0)
                return -EIO;
+       down_read(&chip->shutdown_rwsem);
        while (timeout-- > 0) {
+               if (chip->shutdown)
+                       break;
+               idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);
                if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request,
                                    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                                   validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
-                                   buf, val_len) >= val_len) {
+                                   validx, idx, buf, val_len) >= val_len) {
                        *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
-                       snd_usb_autosuspend(cval->mixer->chip);
-                       return 0;
+                       err = 0;
+                       goto out;
                }
        }
-       snd_usb_autosuspend(cval->mixer->chip);
        snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
-                   request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
-       return -EINVAL;
+                   request, validx, idx, cval->val_type);
+       err = -EINVAL;
+
+ out:
+       up_read(&chip->shutdown_rwsem);
+       snd_usb_autosuspend(cval->mixer->chip);
+       return err;
 }
 
 static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
@@ -313,7 +320,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
        struct snd_usb_audio *chip = cval->mixer->chip;
        unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */
        unsigned char *val;
-       int ret, size;
+       int idx = 0, ret, size;
        __u8 bRequest;
 
        if (request == UAC_GET_CUR) {
@@ -330,16 +337,22 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
        if (ret)
                goto error;
 
-       ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
+       down_read(&chip->shutdown_rwsem);
+       if (chip->shutdown)
+               ret = -ENODEV;
+       else {
+               idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);
+               ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
                              USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                             validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
-                             buf, size);
+                             validx, idx, buf, size);
+       }
+       up_read(&chip->shutdown_rwsem);
        snd_usb_autosuspend(chip);
 
        if (ret < 0) {
 error:
                snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
-                          request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
+                          request, validx, idx, cval->val_type);
                return ret;
        }
 
@@ -417,7 +430,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
 {
        struct snd_usb_audio *chip = cval->mixer->chip;
        unsigned char buf[2];
-       int val_len, err, timeout = 10;
+       int idx = 0, val_len, err, timeout = 10;
 
        if (cval->mixer->protocol == UAC_VERSION_1) {
                val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
@@ -440,19 +453,27 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
        err = snd_usb_autoresume(chip);
        if (err < 0)
                return -EIO;
-       while (timeout-- > 0)
+       down_read(&chip->shutdown_rwsem);
+       while (timeout-- > 0) {
+               if (chip->shutdown)
+                       break;
+               idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);
                if (snd_usb_ctl_msg(chip->dev,
                                    usb_sndctrlpipe(chip->dev, 0), request,
                                    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-                                   validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
-                                   buf, val_len) >= 0) {
-                       snd_usb_autosuspend(chip);
-                       return 0;
+                                   validx, idx, buf, val_len) >= 0) {
+                       err = 0;
+                       goto out;
                }
-       snd_usb_autosuspend(chip);
+       }
        snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n",
-                   request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]);
-       return -EINVAL;
+                   request, validx, idx, cval->val_type, buf[0], buf[1]);
+       err = -EINVAL;
+
+ out:
+       up_read(&chip->shutdown_rwsem);
+       snd_usb_autosuspend(chip);
+       return err;
 }
 
 static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value)
index 690000d..ae2b714 100644 (file)
@@ -283,6 +283,11 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
        if (value > 1)
                return -EINVAL;
        changed = value != mixer->audigy2nx_leds[index];
+       down_read(&mixer->chip->shutdown_rwsem);
+       if (mixer->chip->shutdown) {
+               err = -ENODEV;
+               goto out;
+       }
        if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042))
                err = snd_usb_ctl_msg(mixer->chip->dev,
                              usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
@@ -299,6 +304,8 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
                              usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
                              value, index + 2, NULL, 0);
+ out:
+       up_read(&mixer->chip->shutdown_rwsem);
        if (err < 0)
                return err;
        mixer->audigy2nx_leds[index] = value;
@@ -392,11 +399,16 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry,
 
        for (i = 0; jacks[i].name; ++i) {
                snd_iprintf(buffer, "%s: ", jacks[i].name);
-               err = snd_usb_ctl_msg(mixer->chip->dev,
+               down_read(&mixer->chip->shutdown_rwsem);
+               if (mixer->chip->shutdown)
+                       err = 0;
+               else
+                       err = snd_usb_ctl_msg(mixer->chip->dev,
                                      usb_rcvctrlpipe(mixer->chip->dev, 0),
                                      UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS |
                                      USB_RECIP_INTERFACE, 0,
                                      jacks[i].unitid << 8, buf, 3);
+               up_read(&mixer->chip->shutdown_rwsem);
                if (err == 3 && (buf[0] == 3 || buf[0] == 6))
                        snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]);
                else
@@ -426,10 +438,15 @@ static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol,
        else
                new_status = old_status & ~0x02;
        changed = new_status != old_status;
-       err = snd_usb_ctl_msg(mixer->chip->dev,
+       down_read(&mixer->chip->shutdown_rwsem);
+       if (mixer->chip->shutdown)
+               err = -ENODEV;
+       else
+               err = snd_usb_ctl_msg(mixer->chip->dev,
                              usb_sndctrlpipe(mixer->chip->dev, 0), 0x08,
                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
                              50, 0, &new_status, 1);
+       up_read(&mixer->chip->shutdown_rwsem);
        if (err < 0)
                return err;
        mixer->xonar_u1_status = new_status;
@@ -468,11 +485,17 @@ static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol,
        u8 bRequest = (kcontrol->private_value >> 16) & 0xff;
        u16 wIndex = kcontrol->private_value & 0xffff;
        u8 tmp;
+       int ret;
 
-       int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest,
+       down_read(&mixer->chip->shutdown_rwsem);
+       if (mixer->chip->shutdown)
+               ret = -ENODEV;
+       else
+               ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest,
                                  USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
                                  0, cpu_to_le16(wIndex),
                                  &tmp, sizeof(tmp), 1000);
+       up_read(&mixer->chip->shutdown_rwsem);
 
        if (ret < 0) {
                snd_printk(KERN_ERR
@@ -493,11 +516,17 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol,
        u8 bRequest = (kcontrol->private_value >> 16) & 0xff;
        u16 wIndex = kcontrol->private_value & 0xffff;
        u16 wValue = ucontrol->value.integer.value[0];
+       int ret;
 
-       int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest,
+       down_read(&mixer->chip->shutdown_rwsem);
+       if (mixer->chip->shutdown)
+               ret = -ENODEV;
+       else
+               ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest,
                                  USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
                                  cpu_to_le16(wValue), cpu_to_le16(wIndex),
                                  NULL, 0, 1000);
+       up_read(&mixer->chip->shutdown_rwsem);
 
        if (ret < 0) {
                snd_printk(KERN_ERR
@@ -656,11 +685,16 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl,
                return -EINVAL;
 
 
-       err = snd_usb_ctl_msg(chip->dev,
+       down_read(&mixer->chip->shutdown_rwsem);
+       if (mixer->chip->shutdown)
+               err = -ENODEV;
+       else
+               err = snd_usb_ctl_msg(chip->dev,
                        usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR,
                        USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
                        validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
                        value, val_len);
+       up_read(&mixer->chip->shutdown_rwsem);
        if (err < 0)
                return err;
 
@@ -703,11 +737,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,
 
        if (!pval->is_cached) {
                /* Read current value */
-               err = snd_usb_ctl_msg(chip->dev,
+               down_read(&mixer->chip->shutdown_rwsem);
+               if (mixer->chip->shutdown)
+                       err = -ENODEV;
+               else
+                       err = snd_usb_ctl_msg(chip->dev,
                                usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR,
                                USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
                                validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
                                value, val_len);
+               up_read(&mixer->chip->shutdown_rwsem);
                if (err < 0)
                        return err;
 
@@ -719,11 +758,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,
        if (cur_val != new_val) {
                value[0] = new_val;
                value[1] = 0;
-               err = snd_usb_ctl_msg(chip->dev,
+               down_read(&mixer->chip->shutdown_rwsem);
+               if (mixer->chip->shutdown)
+                       err = -ENODEV;
+               else
+                       err = snd_usb_ctl_msg(chip->dev,
                                usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR,
                                USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
                                validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
                                value, val_len);
+               up_read(&mixer->chip->shutdown_rwsem);
                if (err < 0)
                        return err;
 
index 55e19e1..ef6fa24 100644 (file)
@@ -71,6 +71,8 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream
        unsigned int hwptr_done;
 
        subs = (struct snd_usb_substream *)substream->runtime->private_data;
+       if (subs->stream->chip->shutdown)
+               return SNDRV_PCM_POS_XRUN;
        spin_lock(&subs->lock);
        hwptr_done = subs->hwptr_done;
        substream->runtime->delay = snd_usb_pcm_delay(subs,
@@ -444,7 +446,6 @@ static int configure_endpoint(struct snd_usb_substream *subs)
 {
        int ret;
 
-       mutex_lock(&subs->stream->chip->shutdown_mutex);
        /* format changed */
        stop_endpoints(subs, 0, 0, 0);
        ret = snd_usb_endpoint_set_params(subs->data_endpoint,
@@ -455,19 +456,16 @@ static int configure_endpoint(struct snd_usb_substream *subs)
                                          subs->cur_audiofmt,
                                          subs->sync_endpoint);
        if (ret < 0)
-               goto unlock;
+               return ret;
 
        if (subs->sync_endpoint)
-               ret = snd_usb_endpoint_set_params(subs->data_endpoint,
+               ret = snd_usb_endpoint_set_params(subs->sync_endpoint,
                                                  subs->pcm_format,
                                                  subs->channels,
                                                  subs->period_bytes,
                                                  subs->cur_rate,
                                                  subs->cur_audiofmt,
                                                  NULL);
-
-unlock:
-       mutex_unlock(&subs->stream->chip->shutdown_mutex);
        return ret;
 }
 
@@ -505,7 +503,13 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       if ((ret = set_format(subs, fmt)) < 0)
+       down_read(&subs->stream->chip->shutdown_rwsem);
+       if (subs->stream->chip->shutdown)
+               ret = -ENODEV;
+       else
+               ret = set_format(subs, fmt);
+       up_read(&subs->stream->chip->shutdown_rwsem);
+       if (ret < 0)
                return ret;
 
        subs->interface = fmt->iface;
@@ -527,10 +531,12 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
        subs->cur_audiofmt = NULL;
        subs->cur_rate = 0;
        subs->period_bytes = 0;
-       mutex_lock(&subs->stream->chip->shutdown_mutex);
-       stop_endpoints(subs, 0, 1, 1);
-       deactivate_endpoints(subs);
-       mutex_unlock(&subs->stream->chip->shutdown_mutex);
+       down_read(&subs->stream->chip->shutdown_rwsem);
+       if (!subs->stream->chip->shutdown) {
+               stop_endpoints(subs, 0, 1, 1);
+               deactivate_endpoints(subs);
+       }
+       up_read(&subs->stream->chip->shutdown_rwsem);
        return snd_pcm_lib_free_vmalloc_buffer(substream);
 }
 
@@ -552,12 +558,22 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
                return -ENXIO;
        }
 
-       if (snd_BUG_ON(!subs->data_endpoint))
-               return -EIO;
+       down_read(&subs->stream->chip->shutdown_rwsem);
+       if (subs->stream->chip->shutdown) {
+               ret = -ENODEV;
+               goto unlock;
+       }
+       if (snd_BUG_ON(!subs->data_endpoint)) {
+               ret = -EIO;
+               goto unlock;
+       }
+
+       snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint);
+       snd_usb_endpoint_sync_pending_stop(subs->data_endpoint);
 
        ret = set_format(subs, subs->cur_audiofmt);
        if (ret < 0)
-               return ret;
+               goto unlock;
 
        iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface);
        alts = &iface->altsetting[subs->cur_audiofmt->altset_idx];
@@ -567,12 +583,12 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
                                       subs->cur_audiofmt,
                                       subs->cur_rate);
        if (ret < 0)
-               return ret;
+               goto unlock;
 
        if (subs->need_setup_ep) {
                ret = configure_endpoint(subs);
                if (ret < 0)
-                       return ret;
+                       goto unlock;
                subs->need_setup_ep = false;
        }
 
@@ -592,9 +608,11 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
        /* for playback, submit the URBs now; otherwise, the first hwptr_done
         * updates for all URBs would happen at the same time when starting */
        if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK)
-               return start_endpoints(subs, 1);
+               ret = start_endpoints(subs, 1);
 
-       return 0;
+ unlock:
+       up_read(&subs->stream->chip->shutdown_rwsem);
+       return ret;
 }
 
 static struct snd_pcm_hardware snd_usb_hardware =
@@ -647,7 +665,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs,
                return 0;
        }
        /* check whether the period time is >= the data packet interval */
-       if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) {
+       if (subs->speed != USB_SPEED_FULL) {
                ptime = 125 * (1 << fp->datainterval);
                if (ptime > pt->max || (ptime == pt->max && pt->openmax)) {
                        hwc_debug("   > check: ptime %u > max %u\n", ptime, pt->max);
@@ -925,7 +943,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
                return err;
 
        param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
-       if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
+       if (subs->speed == USB_SPEED_FULL)
                /* full speed devices have fixed data packet interval */
                ptmin = 1000;
        if (ptmin == 1000)
index ebc1a5b..d218f76 100644 (file)
@@ -108,7 +108,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
                        }
                        snd_iprintf(buffer, "\n");
                }
-               if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL)
+               if (subs->speed != USB_SPEED_FULL)
                        snd_iprintf(buffer, "    Data packet interval: %d us\n",
                                    125 * (1 << fp->datainterval));
                // snd_iprintf(buffer, "    Max Packet Size = %d\n", fp->maxpacksize);
@@ -124,7 +124,7 @@ static void proc_dump_ep_status(struct snd_usb_substream *subs,
                return;
        snd_iprintf(buffer, "    Packet Size = %d\n", ep->curpacksize);
        snd_iprintf(buffer, "    Momentary freq = %u Hz (%#x.%04x)\n",
-                   snd_usb_get_speed(subs->dev) == USB_SPEED_FULL
+                   subs->speed == USB_SPEED_FULL
                    ? get_full_speed_hz(ep->freqm)
                    : get_high_speed_hz(ep->freqm),
                    ep->freqm >> 16, ep->freqm & 0xffff);
index 083ed81..1de0c8c 100644 (file)
@@ -90,6 +90,7 @@ static void snd_usb_init_substream(struct snd_usb_stream *as,
        subs->direction = stream;
        subs->dev = as->chip->dev;
        subs->txfr_quirk = as->chip->txfr_quirk;
+       subs->speed = snd_usb_get_speed(subs->dev);
 
        snd_usb_set_pcm_ops(as->pcm, stream);
 
index b8233eb..ef42797 100644 (file)
@@ -37,7 +37,7 @@ struct snd_usb_audio {
        struct usb_interface *pm_intf;
        u32 usb_id;
        struct mutex mutex;
-       struct mutex shutdown_mutex;
+       struct rw_semaphore shutdown_rwsem;
        unsigned int shutdown:1;
        unsigned int probing:1;
        unsigned int autosuspended:1;   
index 3ae4394..1f9a529 100644 (file)
@@ -31,44 +31,44 @@ help:
        @echo '  clean: a summary clean target to clean _all_ folders'
 
 cpupower: FORCE
-       $(QUIET_SUBDIR0)power/$@/ $(QUIET_SUBDIR1)
+       $(call descend,power/$@)
 
 firewire lguest perf usb virtio vm: FORCE
-       $(QUIET_SUBDIR0)$@/ $(QUIET_SUBDIR1)
+       $(call descend,$@)
 
 selftests: FORCE
-       $(QUIET_SUBDIR0)testing/$@/ $(QUIET_SUBDIR1)
+       $(call descend,testing/$@)
 
 turbostat x86_energy_perf_policy: FORCE
-       $(QUIET_SUBDIR0)power/x86/$@/ $(QUIET_SUBDIR1)
+       $(call descend,power/x86/$@)
 
 cpupower_install:
-       $(QUIET_SUBDIR0)power/$(@:_install=)/ $(QUIET_SUBDIR1) install
+       $(call descend,power/$(@:_install=),install)
 
 firewire_install lguest_install perf_install usb_install virtio_install vm_install:
-       $(QUIET_SUBDIR0)$(@:_install=)/ $(QUIET_SUBDIR1) install
+       $(call descend,$(@:_install=),install)
 
 selftests_install:
-       $(QUIET_SUBDIR0)testing/$(@:_clean=)/ $(QUIET_SUBDIR1) install
+       $(call descend,testing/$(@:_clean=),install)
 
 turbostat_install x86_energy_perf_policy_install:
-       $(QUIET_SUBDIR0)power/x86/$(@:_install=)/ $(QUIET_SUBDIR1) install
+       $(call descend,power/x86/$(@:_install=),install)
 
 install: cpupower_install firewire_install lguest_install perf_install \
                selftests_install turbostat_install usb_install virtio_install \
                vm_install x86_energy_perf_policy_install
 
 cpupower_clean:
-       $(QUIET_SUBDIR0)power/cpupower/ $(QUIET_SUBDIR1) clean
+       $(call descend,power/cpupower,clean)
 
 firewire_clean lguest_clean perf_clean usb_clean virtio_clean vm_clean:
-       $(QUIET_SUBDIR0)$(@:_clean=)/ $(QUIET_SUBDIR1) clean
+       $(call descend,$(@:_clean=),clean)
 
 selftests_clean:
-       $(QUIET_SUBDIR0)testing/$(@:_clean=)/ $(QUIET_SUBDIR1) clean
+       $(call descend,testing/$(@:_clean=),clean)
 
 turbostat_clean x86_energy_perf_policy_clean:
-       $(QUIET_SUBDIR0)power/x86/$(@:_clean=)/ $(QUIET_SUBDIR1) clean
+       $(call descend,power/x86/$(@:_clean=),clean)
 
 clean: cpupower_clean firewire_clean lguest_clean perf_clean selftests_clean \
                turbostat_clean usb_clean virtio_clean vm_clean \
index 47264b4..f2989c5 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 ad17855..5ea4326 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);
index f7c968a..0a619af 100644 (file)
@@ -169,7 +169,34 @@ endif
 
 ### --- END CONFIGURATION SECTION ---
 
-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
+ifeq ($(srctree),)
+srctree := $(patsubst %/,%,$(dir $(shell pwd)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+#$(info Determined 'srctree' to be $(srctree))
+endif
+
+ifneq ($(objtree),)
+#$(info Determined 'objtree' to be $(objtree))
+endif
+
+ifneq ($(OUTPUT),)
+#$(info Determined 'OUTPUT' to be $(OUTPUT))
+endif
+
+BASIC_CFLAGS = \
+       -Iutil/include \
+       -Iarch/$(ARCH)/include \
+       $(if $(objtree),-I$(objtree)/arch/$(ARCH)/include/generated/uapi) \
+       -I$(srctree)/arch/$(ARCH)/include/uapi \
+       -I$(srctree)/arch/$(ARCH)/include \
+       $(if $(objtree),-I$(objtree)/include/generated/uapi) \
+       -I$(srctree)/include/uapi \
+       -I$(srctree)/include \
+       -I$(OUTPUT)util \
+       -Iutil \
+       -I. \
+       -I$(TRACE_EVENT_DIR) \
+       -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
 BASIC_LDFLAGS =
 
 # Guard against environment variables
@@ -184,9 +211,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 +238,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:
 #
index 46fc9f1..7fcdcdb 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <stdlib.h>
 #include "../../util/types.h"
-#include "../../../../../arch/x86/include/asm/perf_regs.h"
+#include <asm/perf_regs.h>
 
 #ifndef ARCH_X86_64
 #define PERF_REGS_MASK ((1ULL << PERF_REG_X86_32_MAX) - 1)
index 411ee56..178b88a 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 260abc5..283b439 100644 (file)
 #include <pthread.h>
 #include <math.h>
 
-#include "../../arch/x86/include/asm/svm.h"
-#include "../../arch/x86/include/asm/vmx.h"
-#include "../../arch/x86/include/asm/kvm.h"
+#if defined(__i386__) || defined(__x86_64__)
+#include <asm/svm.h>
+#include <asm/vmx.h>
+#include <asm/kvm.h>
 
 struct event_key {
        #define INVALID_KEY     (~0ULL)
@@ -58,7 +59,7 @@ struct kvm_event_key {
 };
 
 
-struct perf_kvm;
+struct perf_kvm_stat;
 
 struct kvm_events_ops {
        bool (*is_begin_event)(struct perf_evsel *evsel,
@@ -66,7 +67,7 @@ struct kvm_events_ops {
                               struct event_key *key);
        bool (*is_end_event)(struct perf_evsel *evsel,
                             struct perf_sample *sample, struct event_key *key);
-       void (*decode_key)(struct perf_kvm *kvm, struct event_key *key,
+       void (*decode_key)(struct perf_kvm_stat *kvm, struct event_key *key,
                           char decode[20]);
        const char *name;
 };
@@ -79,7 +80,7 @@ struct exit_reasons_table {
 #define EVENTS_BITS            12
 #define EVENTS_CACHE_SIZE      (1UL << EVENTS_BITS)
 
-struct perf_kvm {
+struct perf_kvm_stat {
        struct perf_tool    tool;
        struct perf_session *session;
 
@@ -146,7 +147,7 @@ static struct exit_reasons_table svm_exit_reasons[] = {
        SVM_EXIT_REASONS
 };
 
-static const char *get_exit_reason(struct perf_kvm *kvm, u64 exit_code)
+static const char *get_exit_reason(struct perf_kvm_stat *kvm, u64 exit_code)
 {
        int i = kvm->exit_reasons_size;
        struct exit_reasons_table *tbl = kvm->exit_reasons;
@@ -162,7 +163,7 @@ static const char *get_exit_reason(struct perf_kvm *kvm, u64 exit_code)
        return "UNKNOWN";
 }
 
-static void exit_event_decode_key(struct perf_kvm *kvm,
+static void exit_event_decode_key(struct perf_kvm_stat *kvm,
                                  struct event_key *key,
                                  char decode[20])
 {
@@ -228,7 +229,7 @@ static bool mmio_event_end(struct perf_evsel *evsel, struct perf_sample *sample,
        return false;
 }
 
-static void mmio_event_decode_key(struct perf_kvm *kvm __maybe_unused,
+static void mmio_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused,
                                  struct event_key *key,
                                  char decode[20])
 {
@@ -271,7 +272,7 @@ static bool ioport_event_end(struct perf_evsel *evsel,
        return kvm_entry_event(evsel);
 }
 
-static void ioport_event_decode_key(struct perf_kvm *kvm __maybe_unused,
+static void ioport_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused,
                                    struct event_key *key,
                                    char decode[20])
 {
@@ -286,7 +287,7 @@ static struct kvm_events_ops ioport_events = {
        .name = "IO Port Access"
 };
 
-static bool register_kvm_events_ops(struct perf_kvm *kvm)
+static bool register_kvm_events_ops(struct perf_kvm_stat *kvm)
 {
        bool ret = true;
 
@@ -311,7 +312,7 @@ struct vcpu_event_record {
 };
 
 
-static void init_kvm_event_record(struct perf_kvm *kvm)
+static void init_kvm_event_record(struct perf_kvm_stat *kvm)
 {
        int i;
 
@@ -360,7 +361,7 @@ static struct kvm_event *kvm_alloc_init_event(struct event_key *key)
        return event;
 }
 
-static struct kvm_event *find_create_kvm_event(struct perf_kvm *kvm,
+static struct kvm_event *find_create_kvm_event(struct perf_kvm_stat *kvm,
                                               struct event_key *key)
 {
        struct kvm_event *event;
@@ -381,7 +382,7 @@ static struct kvm_event *find_create_kvm_event(struct perf_kvm *kvm,
        return event;
 }
 
-static bool handle_begin_event(struct perf_kvm *kvm,
+static bool handle_begin_event(struct perf_kvm_stat *kvm,
                               struct vcpu_event_record *vcpu_record,
                               struct event_key *key, u64 timestamp)
 {
@@ -425,7 +426,7 @@ static bool update_kvm_event(struct kvm_event *event, int vcpu_id,
        return true;
 }
 
-static bool handle_end_event(struct perf_kvm *kvm,
+static bool handle_end_event(struct perf_kvm_stat *kvm,
                             struct vcpu_event_record *vcpu_record,
                             struct event_key *key,
                             u64 timestamp)
@@ -486,7 +487,7 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread,
        return thread->priv;
 }
 
-static bool handle_kvm_event(struct perf_kvm *kvm,
+static bool handle_kvm_event(struct perf_kvm_stat *kvm,
                             struct thread *thread,
                             struct perf_evsel *evsel,
                             struct perf_sample *sample)
@@ -541,7 +542,7 @@ static struct kvm_event_key keys[] = {
        { NULL, NULL }
 };
 
-static bool select_key(struct perf_kvm *kvm)
+static bool select_key(struct perf_kvm_stat *kvm)
 {
        int i;
 
@@ -577,7 +578,8 @@ static void insert_to_result(struct rb_root *result, struct kvm_event *event,
        rb_insert_color(&event->rb, result);
 }
 
-static void update_total_count(struct perf_kvm *kvm, struct kvm_event *event)
+static void
+update_total_count(struct perf_kvm_stat *kvm, struct kvm_event *event)
 {
        int vcpu = kvm->trace_vcpu;
 
@@ -590,7 +592,7 @@ static bool event_is_valid(struct kvm_event *event, int vcpu)
        return !!get_event_count(event, vcpu);
 }
 
-static void sort_result(struct perf_kvm *kvm)
+static void sort_result(struct perf_kvm_stat *kvm)
 {
        unsigned int i;
        int vcpu = kvm->trace_vcpu;
@@ -627,7 +629,7 @@ static void print_vcpu_info(int vcpu)
                pr_info("VCPU %d:\n\n", vcpu);
 }
 
-static void print_result(struct perf_kvm *kvm)
+static void print_result(struct perf_kvm_stat *kvm)
 {
        char decode[20];
        struct kvm_event *event;
@@ -670,7 +672,8 @@ static int process_sample_event(struct perf_tool *tool,
                                struct machine *machine)
 {
        struct thread *thread = machine__findnew_thread(machine, sample->tid);
-       struct perf_kvm *kvm = container_of(tool, struct perf_kvm, tool);
+       struct perf_kvm_stat *kvm = container_of(tool, struct perf_kvm_stat,
+                                                tool);
 
        if (thread == NULL) {
                pr_debug("problem processing %d event, skipping it.\n",
@@ -701,7 +704,7 @@ static int get_cpu_isa(struct perf_session *session)
        return isa;
 }
 
-static int read_events(struct perf_kvm *kvm)
+static int read_events(struct perf_kvm_stat *kvm)
 {
        int ret;
 
@@ -750,7 +753,7 @@ static bool verify_vcpu(int vcpu)
        return true;
 }
 
-static int kvm_events_report_vcpu(struct perf_kvm *kvm)
+static int kvm_events_report_vcpu(struct perf_kvm_stat *kvm)
 {
        int ret = -EINVAL;
        int vcpu = kvm->trace_vcpu;
@@ -798,7 +801,8 @@ static const char * const record_args[] = {
                _p;                     \
        })
 
-static int kvm_events_record(struct perf_kvm *kvm, int argc, const char **argv)
+static int
+kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
 {
        unsigned int rec_argc, i, j;
        const char **rec_argv;
@@ -821,7 +825,8 @@ static int kvm_events_record(struct perf_kvm *kvm, int argc, const char **argv)
        return cmd_record(i, rec_argv, NULL);
 }
 
-static int kvm_events_report(struct perf_kvm *kvm, int argc, const char **argv)
+static int
+kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
 {
        const struct option kvm_events_report_options[] = {
                OPT_STRING(0, "event", &kvm->report_event, "report event",
@@ -864,24 +869,37 @@ static void print_kvm_stat_usage(void)
        printf("\nOtherwise, it is the alias of 'perf stat':\n");
 }
 
-static int kvm_cmd_stat(struct perf_kvm *kvm, int argc, const char **argv)
+static int kvm_cmd_stat(const char *file_name, int argc, const char **argv)
 {
+       struct perf_kvm_stat kvm = {
+               .file_name = file_name,
+
+               .trace_vcpu     = -1,
+               .report_event   = "vmexit",
+               .sort_key       = "sample",
+
+               .exit_reasons = svm_exit_reasons,
+               .exit_reasons_size = ARRAY_SIZE(svm_exit_reasons),
+               .exit_reasons_isa = "SVM",
+       };
+
        if (argc == 1) {
                print_kvm_stat_usage();
                goto perf_stat;
        }
 
        if (!strncmp(argv[1], "rec", 3))
-               return kvm_events_record(kvm, argc - 1, argv + 1);
+               return kvm_events_record(&kvm, argc - 1, argv + 1);
 
        if (!strncmp(argv[1], "rep", 3))
-               return kvm_events_report(kvm, argc - 1 , argv + 1);
+               return kvm_events_report(&kvm, argc - 1 , argv + 1);
 
 perf_stat:
        return cmd_stat(argc, argv, NULL);
 }
+#endif
 
-static int __cmd_record(struct perf_kvm *kvm, int argc, const char **argv)
+static int __cmd_record(const char *file_name, int argc, const char **argv)
 {
        int rec_argc, i = 0, j;
        const char **rec_argv;
@@ -890,7 +908,7 @@ static int __cmd_record(struct perf_kvm *kvm, int argc, const char **argv)
        rec_argv = calloc(rec_argc + 1, sizeof(char *));
        rec_argv[i++] = strdup("record");
        rec_argv[i++] = strdup("-o");
-       rec_argv[i++] = strdup(kvm->file_name);
+       rec_argv[i++] = strdup(file_name);
        for (j = 1; j < argc; j++, i++)
                rec_argv[i] = argv[j];
 
@@ -899,7 +917,7 @@ static int __cmd_record(struct perf_kvm *kvm, int argc, const char **argv)
        return cmd_record(i, rec_argv, NULL);
 }
 
-static int __cmd_report(struct perf_kvm *kvm, int argc, const char **argv)
+static int __cmd_report(const char *file_name, int argc, const char **argv)
 {
        int rec_argc, i = 0, j;
        const char **rec_argv;
@@ -908,7 +926,7 @@ static int __cmd_report(struct perf_kvm *kvm, int argc, const char **argv)
        rec_argv = calloc(rec_argc + 1, sizeof(char *));
        rec_argv[i++] = strdup("report");
        rec_argv[i++] = strdup("-i");
-       rec_argv[i++] = strdup(kvm->file_name);
+       rec_argv[i++] = strdup(file_name);
        for (j = 1; j < argc; j++, i++)
                rec_argv[i] = argv[j];
 
@@ -917,7 +935,8 @@ static int __cmd_report(struct perf_kvm *kvm, int argc, const char **argv)
        return cmd_report(i, rec_argv, NULL);
 }
 
-static int __cmd_buildid_list(struct perf_kvm *kvm, int argc, const char **argv)
+static int
+__cmd_buildid_list(const char *file_name, int argc, const char **argv)
 {
        int rec_argc, i = 0, j;
        const char **rec_argv;
@@ -926,7 +945,7 @@ static int __cmd_buildid_list(struct perf_kvm *kvm, int argc, const char **argv)
        rec_argv = calloc(rec_argc + 1, sizeof(char *));
        rec_argv[i++] = strdup("buildid-list");
        rec_argv[i++] = strdup("-i");
-       rec_argv[i++] = strdup(kvm->file_name);
+       rec_argv[i++] = strdup(file_name);
        for (j = 1; j < argc; j++, i++)
                rec_argv[i] = argv[j];
 
@@ -937,20 +956,12 @@ static int __cmd_buildid_list(struct perf_kvm *kvm, int argc, const char **argv)
 
 int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
 {
-       struct perf_kvm kvm = {
-               .trace_vcpu     = -1,
-               .report_event   = "vmexit",
-               .sort_key       = "sample",
-
-               .exit_reasons = svm_exit_reasons,
-               .exit_reasons_size = ARRAY_SIZE(svm_exit_reasons),
-               .exit_reasons_isa = "SVM",
-       };
+       const char *file_name;
 
        const struct option kvm_options[] = {
-               OPT_STRING('i', "input", &kvm.file_name, "file",
+               OPT_STRING('i', "input", &file_name, "file",
                           "Input file name"),
-               OPT_STRING('o', "output", &kvm.file_name, "file",
+               OPT_STRING('o', "output", &file_name, "file",
                           "Output file name"),
                OPT_BOOLEAN(0, "guest", &perf_guest,
                            "Collect guest os data"),
@@ -985,32 +996,34 @@ int cmd_kvm(int argc, const char **argv, const char *prefix __maybe_unused)
        if (!perf_host)
                perf_guest = 1;
 
-       if (!kvm.file_name) {
+       if (!file_name) {
                if (perf_host && !perf_guest)
-                       kvm.file_name = strdup("perf.data.host");
+                       file_name = strdup("perf.data.host");
                else if (!perf_host && perf_guest)
-                       kvm.file_name = strdup("perf.data.guest");
+                       file_name = strdup("perf.data.guest");
                else
-                       kvm.file_name = strdup("perf.data.kvm");
+                       file_name = strdup("perf.data.kvm");
 
-               if (!kvm.file_name) {
+               if (!file_name) {
                        pr_err("Failed to allocate memory for filename\n");
                        return -ENOMEM;
                }
        }
 
        if (!strncmp(argv[0], "rec", 3))
-               return __cmd_record(&kvm, argc, argv);
+               return __cmd_record(file_name, argc, argv);
        else if (!strncmp(argv[0], "rep", 3))
-               return __cmd_report(&kvm, argc, argv);
+               return __cmd_report(file_name, argc, argv);
        else if (!strncmp(argv[0], "diff", 4))
                return cmd_diff(argc, argv, NULL);
        else if (!strncmp(argv[0], "top", 3))
                return cmd_top(argc, argv, NULL);
        else if (!strncmp(argv[0], "buildid-list", 12))
-               return __cmd_buildid_list(&kvm, argc, argv);
+               return __cmd_buildid_list(file_name, argc, argv);
+#if defined(__i386__) || defined(__x86_64__)
        else if (!strncmp(argv[0], "stat", 4))
-               return kvm_cmd_stat(&kvm, argc, argv);
+               return kvm_cmd_stat(file_name, argc, argv);
+#endif
        else
                usage_with_options(kvm_usage, kvm_options);
 
index 484f26c..5acd6e8 100644 (file)
@@ -15,7 +15,7 @@
 #include "util/thread_map.h"
 #include "util/pmu.h"
 #include "event-parse.h"
-#include "../../include/linux/hw_breakpoint.h"
+#include <linux/hw_breakpoint.h>
 
 #include <sys/mman.h>
 
index dec8ced..7aaee39 100644 (file)
@@ -56,6 +56,10 @@ 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 +79,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);
@@ -267,6 +268,13 @@ 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);
                }
index 2762877..238f923 100644 (file)
@@ -5,8 +5,9 @@ struct winsize;
 
 void get_term_dimensions(struct winsize *ws);
 
+#include <asm/unistd.h>
+
 #if defined(__i386__)
-#include "../../arch/x86/include/asm/unistd.h"
 #define rmb()          asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
 #define cpu_relax()    asm volatile("rep; nop" ::: "memory");
 #define CPUINFO_PROC   "model name"
@@ -16,7 +17,6 @@ void get_term_dimensions(struct winsize *ws);
 #endif
 
 #if defined(__x86_64__)
-#include "../../arch/x86/include/asm/unistd.h"
 #define rmb()          asm volatile("lfence" ::: "memory")
 #define cpu_relax()    asm volatile("rep; nop" ::: "memory");
 #define CPUINFO_PROC   "model name"
@@ -26,20 +26,17 @@ void get_term_dimensions(struct winsize *ws);
 #endif
 
 #ifdef __powerpc__
-#include "../../arch/powerpc/include/asm/unistd.h"
 #define rmb()          asm volatile ("sync" ::: "memory")
 #define cpu_relax()    asm volatile ("" ::: "memory");
 #define CPUINFO_PROC   "cpu"
 #endif
 
 #ifdef __s390__
-#include "../../arch/s390/include/asm/unistd.h"
 #define rmb()          asm volatile("bcr 15,0" ::: "memory")
 #define cpu_relax()    asm volatile("" ::: "memory");
 #endif
 
 #ifdef __sh__
-#include "../../arch/sh/include/asm/unistd.h"
 #if defined(__SH4A__) || defined(__SH5__)
 # define rmb()         asm volatile("synco" ::: "memory")
 #else
@@ -50,35 +47,30 @@ void get_term_dimensions(struct winsize *ws);
 #endif
 
 #ifdef __hppa__
-#include "../../arch/parisc/include/asm/unistd.h"
 #define rmb()          asm volatile("" ::: "memory")
 #define cpu_relax()    asm volatile("" ::: "memory");
 #define CPUINFO_PROC   "cpu"
 #endif
 
 #ifdef __sparc__
-#include "../../arch/sparc/include/asm/unistd.h"
 #define rmb()          asm volatile("":::"memory")
 #define cpu_relax()    asm volatile("":::"memory")
 #define CPUINFO_PROC   "cpu"
 #endif
 
 #ifdef __alpha__
-#include "../../arch/alpha/include/asm/unistd.h"
 #define rmb()          asm volatile("mb" ::: "memory")
 #define cpu_relax()    asm volatile("" ::: "memory")
 #define CPUINFO_PROC   "cpu model"
 #endif
 
 #ifdef __ia64__
-#include "../../arch/ia64/include/asm/unistd.h"
 #define rmb()          asm volatile ("mf" ::: "memory")
 #define cpu_relax()    asm volatile ("hint @pause" ::: "memory")
 #define CPUINFO_PROC   "model name"
 #endif
 
 #ifdef __arm__
-#include "../../arch/arm/include/asm/unistd.h"
 /*
  * Use the __kuser_memory_barrier helper in the CPU helper page. See
  * arch/arm/kernel/entry-armv.S in the kernel source for details.
@@ -89,13 +81,11 @@ void get_term_dimensions(struct winsize *ws);
 #endif
 
 #ifdef __aarch64__
-#include "../../arch/arm64/include/asm/unistd.h"
 #define rmb()          asm volatile("dmb ld" ::: "memory")
 #define cpu_relax()    asm volatile("yield" ::: "memory")
 #endif
 
 #ifdef __mips__
-#include "../../arch/mips/include/asm/unistd.h"
 #define rmb()          asm volatile(                                   \
                                ".set   mips2\n\t"                      \
                                "sync\n\t"                              \
@@ -112,7 +102,7 @@ void get_term_dimensions(struct winsize *ws);
 #include <sys/types.h>
 #include <sys/syscall.h>
 
-#include "../../include/uapi/linux/perf_event.h"
+#include <linux/perf_event.h>
 #include "util/types.h"
 #include <stdbool.h>
 
index 0568536..ef2f93c 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 618d411..d144d46 100644 (file)
@@ -18,8 +18,8 @@
 #include "cpumap.h"
 #include "thread_map.h"
 #include "target.h"
-#include "../../../include/linux/hw_breakpoint.h"
-#include "../../../include/uapi/linux/perf_event.h"
+#include <linux/hw_breakpoint.h>
+#include <linux/perf_event.h>
 #include "perf_regs.h"
 
 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
index 6f94d6d..d99b476 100644 (file)
@@ -3,7 +3,8 @@
 
 #include <linux/list.h>
 #include <stdbool.h>
-#include "../../../include/uapi/linux/perf_event.h"
+#include <stddef.h>
+#include <linux/perf_event.h>
 #include "types.h"
 #include "xyarray.h"
 #include "cgroup.h"
index 7daad23..566b84c 100644 (file)
@@ -1378,6 +1378,8 @@ static void print_numa_topology(struct perf_header *ph, int fd __maybe_unused,
 
                str = tmp + 1;
                fprintf(fp, "# node%u cpu list : %s\n", c, str);
+
+               str += strlen(str) + 1;
        }
        return;
 error:
index 879d215..9bc0078 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __PERF_HEADER_H
 #define __PERF_HEADER_H
 
-#include "../../../include/uapi/linux/perf_event.h"
+#include <linux/perf_event.h>
 #include <sys/types.h>
 #include <stdbool.h>
 #include "types.h"
index 28c18d1..6ef213b 100644 (file)
@@ -3,7 +3,7 @@
 #include "evsel.h"
 #include "evlist.h"
 #include "sysfs.h"
-#include "../../../include/linux/hw_breakpoint.h"
+#include <linux/hw_breakpoint.h>
 
 #define TEST_ASSERT_VAL(text, cond) \
 do { \
@@ -513,7 +513,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 +600,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 +664,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 +679,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);
index aed38e4..6b6d03e 100644 (file)
@@ -1,4 +1,4 @@
-#include "../../../include/linux/hw_breakpoint.h"
+#include <linux/hw_breakpoint.h>
 #include "util.h"
 #include "../perf.h"
 #include "evlist.h"
@@ -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;
 
index 839230c..2820c40 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/list.h>
 #include <stdbool.h>
 #include "types.h"
-#include "../../../include/uapi/linux/perf_event.h"
+#include <linux/perf_event.h>
 #include "types.h"
 
 struct list_head;
index 39f3aba..fdeb8ac 100644 (file)
@@ -2,7 +2,7 @@
 #define __PMU_H
 
 #include <linux/bitops.h>
-#include "../../../include/uapi/linux/perf_event.h"
+#include <linux/perf_event.h>
 
 enum {
        PERF_PMU_FORMAT_VALUE_CONFIG,
index dd64261..0eae00a 100644 (file)
@@ -7,7 +7,7 @@
 #include "symbol.h"
 #include "thread.h"
 #include <linux/rbtree.h>
-#include "../../../include/uapi/linux/perf_event.h"
+#include <linux/perf_event.h>
 
 struct sample_queue;
 struct ip_callchain;
index d0f9f29..73d5102 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 b5b1b92..cfd1c0f 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 2eeb51b..cfa9068 100644 (file)
@@ -90,17 +90,17 @@ void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
        if (!strbuf_avail(sb))
                strbuf_grow(sb, 64);
        va_start(ap, fmt);
-       len = vscnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
+       len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
        va_end(ap);
        if (len < 0)
-               die("your vscnprintf is broken");
+               die("your vsnprintf is broken");
        if (len > strbuf_avail(sb)) {
                strbuf_grow(sb, len);
                va_start(ap, fmt);
-               len = vscnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
+               len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
                va_end(ap);
                if (len > strbuf_avail(sb)) {
-                       die("this should not happen, your snprintf is broken");
+                       die("this should not happen, your vsnprintf is broken");
                }
        }
        strbuf_setlen(sb, sb->len + len);
index fb4b7ea..8b3e593 100644 (file)
@@ -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;
 }
index 8a83dd2..d42073f 100644 (file)
@@ -20,3 +20,10 @@ utils/cpufreq-set.o
 utils/cpufreq-aperf.o
 cpupower
 bench/cpufreq-bench
+debug/kernel/Module.symvers
+debug/i386/centrino-decode
+debug/i386/dump_psb
+debug/i386/intel_gsic
+debug/i386/powernow-k8-decode
+debug/x86_64/centrino-decode
+debug/x86_64/powernow-k8-decode
index cf397bd..d875a74 100644 (file)
@@ -253,7 +253,8 @@ clean:
         | xargs rm -f
        -rm -f $(OUTPUT)cpupower
        -rm -f $(OUTPUT)libcpupower.so*
-       -rm -rf $(OUTPUT)po/*.{gmo,pot}
+       -rm -rf $(OUTPUT)po/*.gmo
+       -rm -rf $(OUTPUT)po/*.pot
        $(MAKE) -C bench O=$(OUTPUT) clean
 
 
index 3ba158f..c05cc0a 100644 (file)
@@ -26,7 +26,10 @@ $(OUTPUT)powernow-k8-decode: powernow-k8-decode.c
 all: $(OUTPUT)centrino-decode $(OUTPUT)dump_psb $(OUTPUT)intel_gsic $(OUTPUT)powernow-k8-decode
 
 clean:
-       rm -rf $(OUTPUT){centrino-decode,dump_psb,intel_gsic,powernow-k8-decode}
+       rm -rf $(OUTPUT)centrino-decode
+       rm -rf $(OUTPUT)dump_psb
+       rm -rf $(OUTPUT)intel_gsic
+       rm -rf $(OUTPUT)powernow-k8-decode
 
 install:
        $(INSTALL) -d $(DESTDIR)${bindir}
index 1141c20..e01c35d 100644 (file)
@@ -7,11 +7,11 @@ cpupower\-monitor \- Report processor frequency and idle statistics
 .RB "\-l"
 
 .B cpupower monitor
-.RB [ "\-m <mon1>," [ "<mon2>,..." ] ]
+.RB [ -c ] [ "\-m <mon1>," [ "<mon2>,..." ] ]
 .RB [ "\-i seconds" ]
 .br
 .B cpupower monitor
-.RB [ "\-m <mon1>," [ "<mon2>,..." ] ]
+.RB [ -c ][ "\-m <mon1>," [ "<mon2>,..." ] ]
 .RB command
 .br
 .SH DESCRIPTION
@@ -64,6 +64,17 @@ Only display specific monitors. Use the monitor string(s) provided by \-l option
 Measure intervall.
 .RE
 .PP
+\-c
+.RS 4
+Schedule the process on every core before starting and ending measuring.
+This could be needed for the Idle_Stats monitor when no other MSR based
+monitor (has to be run on the core that is measured) is run in parallel.
+This is to wake up the processors from deeper sleep states and let the
+kernel re
+-account its cpuidle (C-state) information before reading the
+cpuidle timings from sysfs.
+.RE
+.PP
 command
 .RS 4
 Measure idle and frequency characteristics of an arbitrary command/workload.
index 906895d..93b0aa7 100644 (file)
@@ -158,6 +158,8 @@ out:
                                cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO;
                        case 0x2A:      /* SNB */
                        case 0x2D:      /* SNB Xeon */
+                       case 0x3A:      /* IVB */
+                       case 0x3E:      /* IVB Xeon */
                                cpu_info->caps |= CPUPOWER_CAP_HAS_TURBO_RATIO;
                                cpu_info->caps |= CPUPOWER_CAP_IS_SNB;
                                break;
index 2eb584c..aa9e954 100644 (file)
@@ -92,6 +92,14 @@ extern int get_cpu_info(unsigned int cpu, struct cpupower_cpu_info *cpu_info);
 extern struct cpupower_cpu_info cpupower_cpu_info;
 /* cpuid and cpuinfo helpers  **************************/
 
+struct cpuid_core_info {
+       int pkg;
+       int core;
+       int cpu;
+
+       /* flags */
+       unsigned int is_online:1;
+};
 
 /* CPU topology/hierarchy parsing ******************/
 struct cpupower_topology {
@@ -101,18 +109,12 @@ struct cpupower_topology {
        unsigned int threads; /* per core */
 
        /* Array gets mallocated with cores entries, holding per core info */
-       struct {
-               int pkg;
-               int core;
-               int cpu;
-
-               /* flags */
-               unsigned int is_online:1;
-       } *core_info;
+       struct cpuid_core_info *core_info;
 };
 
 extern int get_cpu_topology(struct cpupower_topology *cpu_top);
 extern void cpu_topology_release(struct cpupower_topology cpu_top);
+
 /* CPU topology/hierarchy parsing ******************/
 
 /* X86 ONLY ****************************************/
index 96e28c1..38ab916 100644 (file)
@@ -37,25 +37,6 @@ unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen)
        return (unsigned int) numread;
 }
 
-static unsigned int sysfs_write_file(const char *path,
-                                    const char *value, size_t len)
-{
-       int fd;
-       ssize_t numwrite;
-
-       fd = open(path, O_WRONLY);
-       if (fd == -1)
-               return 0;
-
-       numwrite = write(fd, value, len);
-       if (numwrite < 1) {
-               close(fd);
-               return 0;
-       }
-       close(fd);
-       return (unsigned int) numwrite;
-}
-
 /*
  * Detect whether a CPU is online
  *
index 4eae2c4..c13120a 100644 (file)
@@ -20,9 +20,8 @@
 #include <helpers/sysfs.h>
 
 /* returns -1 on failure, 0 on success */
-int sysfs_topology_read_file(unsigned int cpu, const char *fname)
+static int sysfs_topology_read_file(unsigned int cpu, const char *fname, int *result)
 {
-       unsigned long value;
        char linebuf[MAX_LINE_LEN];
        char *endp;
        char path[SYSFS_PATH_MAX];
@@ -31,20 +30,12 @@ int sysfs_topology_read_file(unsigned int cpu, const char *fname)
                         cpu, fname);
        if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0)
                return -1;
-       value = strtoul(linebuf, &endp, 0);
+       *result = strtol(linebuf, &endp, 0);
        if (endp == linebuf || errno == ERANGE)
                return -1;
-       return value;
+       return 0;
 }
 
-struct cpuid_core_info {
-       unsigned int pkg;
-       unsigned int thread;
-       unsigned int cpu;
-       /* flags */
-       unsigned int is_online:1;
-};
-
 static int __compare(const void *t1, const void *t2)
 {
        struct cpuid_core_info *top1 = (struct cpuid_core_info *)t1;
@@ -53,9 +44,9 @@ static int __compare(const void *t1, const void *t2)
                return -1;
        else if (top1->pkg > top2->pkg)
                return 1;
-       else if (top1->thread < top2->thread)
+       else if (top1->core < top2->core)
                return -1;
-       else if (top1->thread > top2->thread)
+       else if (top1->core > top2->core)
                return 1;
        else if (top1->cpu < top2->cpu)
                return -1;
@@ -73,28 +64,42 @@ static int __compare(const void *t1, const void *t2)
  */
 int get_cpu_topology(struct cpupower_topology *cpu_top)
 {
-       int cpu, cpus = sysconf(_SC_NPROCESSORS_CONF);
+       int cpu, last_pkg, cpus = sysconf(_SC_NPROCESSORS_CONF);
 
-       cpu_top->core_info = malloc(sizeof(struct cpupower_topology) * cpus);
+       cpu_top->core_info = malloc(sizeof(struct cpuid_core_info) * cpus);
        if (cpu_top->core_info == NULL)
                return -ENOMEM;
        cpu_top->pkgs = cpu_top->cores = 0;
        for (cpu = 0; cpu < cpus; cpu++) {
                cpu_top->core_info[cpu].cpu = cpu;
                cpu_top->core_info[cpu].is_online = sysfs_is_cpu_online(cpu);
-               cpu_top->core_info[cpu].pkg =
-                       sysfs_topology_read_file(cpu, "physical_package_id");
-               if ((int)cpu_top->core_info[cpu].pkg != -1 &&
-                   cpu_top->core_info[cpu].pkg > cpu_top->pkgs)
-                       cpu_top->pkgs = cpu_top->core_info[cpu].pkg;
-               cpu_top->core_info[cpu].core =
-                       sysfs_topology_read_file(cpu, "core_id");
+               if(sysfs_topology_read_file(
+                       cpu,
+                       "physical_package_id",
+                       &(cpu_top->core_info[cpu].pkg)) < 0)
+                       return -1;
+               if(sysfs_topology_read_file(
+                       cpu,
+                       "core_id",
+                       &(cpu_top->core_info[cpu].core)) < 0)
+                       return -1;
        }
-       cpu_top->pkgs++;
 
        qsort(cpu_top->core_info, cpus, sizeof(struct cpuid_core_info),
              __compare);
 
+       /* Count the number of distinct pkgs values. This works
+          because the primary sort of the core_info struct was just
+          done by pkg value. */
+       last_pkg = cpu_top->core_info[0].pkg;
+       for(cpu = 1; cpu < cpus; cpu++) {
+               if(cpu_top->core_info[cpu].pkg != last_pkg) {
+                       last_pkg = cpu_top->core_info[cpu].pkg;
+                       cpu_top->pkgs++;
+               }
+       }
+       cpu_top->pkgs++;
+
        /* Intel's cores count is not consecutively numbered, there may
         * be a core_id of 3, but none of 2. Assume there always is 0
         * Get amount of cores by counting duplicates in a package
index 0d6571e..c4bae92 100644 (file)
@@ -39,6 +39,7 @@ static int mode;
 static int interval = 1;
 static char *show_monitors_param;
 static struct cpupower_topology cpu_top;
+static unsigned int wake_cpus;
 
 /* ToDo: Document this in the manpage */
 static char range_abbr[RANGE_MAX] = { 'T', 'C', 'P', 'M', };
@@ -84,7 +85,7 @@ int fill_string_with_spaces(char *s, int n)
 void print_header(int topology_depth)
 {
        int unsigned mon;
-       int state, need_len, pr_mon_len;
+       int state, need_len;
        cstate_t s;
        char buf[128] = "";
        int percent_width = 4;
@@ -93,7 +94,6 @@ void print_header(int topology_depth)
        printf("%s|", buf);
 
        for (mon = 0; mon < avail_monitors; mon++) {
-               pr_mon_len = 0;
                need_len = monitors[mon]->hw_states_num * (percent_width + 3)
                        - 1;
                if (mon != 0) {
@@ -315,16 +315,28 @@ int fork_it(char **argv)
 int do_interval_measure(int i)
 {
        unsigned int num;
+       int cpu;
+
+       if (wake_cpus)
+               for (cpu = 0; cpu < cpu_count; cpu++)
+                       bind_cpu(cpu);
 
        for (num = 0; num < avail_monitors; num++) {
                dprint("HW C-state residency monitor: %s - States: %d\n",
                       monitors[num]->name, monitors[num]->hw_states_num);
                monitors[num]->start();
        }
+
        sleep(i);
+
+       if (wake_cpus)
+               for (cpu = 0; cpu < cpu_count; cpu++)
+                       bind_cpu(cpu);
+
        for (num = 0; num < avail_monitors; num++)
                monitors[num]->stop();
 
+
        return 0;
 }
 
@@ -333,7 +345,7 @@ static void cmdline(int argc, char *argv[])
        int opt;
        progname = basename(argv[0]);
 
-       while ((opt = getopt(argc, argv, "+li:m:")) != -1) {
+       while ((opt = getopt(argc, argv, "+lci:m:")) != -1) {
                switch (opt) {
                case 'l':
                        if (mode)
@@ -352,6 +364,9 @@ static void cmdline(int argc, char *argv[])
                        mode = show;
                        show_monitors_param = optarg;
                        break;
+               case 'c':
+                       wake_cpus = 1;
+                       break;
                default:
                        print_wrong_arg_exit();
                }
index 9312ee1..9e43f33 100644 (file)
@@ -65,4 +65,21 @@ extern long long timespec_diff_us(struct timespec start, struct timespec end);
                                "could be inaccurate\n"), mes, ov);             \
 }
 
+
+/* Taken over from x86info project sources  -> return 0 on success */
+#include <sched.h>
+#include <sys/types.h>
+#include <unistd.h>
+static inline int bind_cpu(int cpu)
+{
+       cpu_set_t set;
+
+       if (sched_getaffinity(getpid(), sizeof(set), &set) == 0) {
+               CPU_ZERO(&set);
+               CPU_SET(cpu, &set);
+               return sched_setaffinity(getpid(), sizeof(set), &set);
+       }
+       return 1;
+}
+
 #endif /* __CPUIDLE_INFO_HW__ */
index a1bc07c..a99b43b 100644 (file)
@@ -150,9 +150,15 @@ static struct cpuidle_monitor *snb_register(void)
            || cpupower_cpu_info.family != 6)
                return NULL;
 
-       if (cpupower_cpu_info.model != 0x2A
-           && cpupower_cpu_info.model != 0x2D)
+       switch (cpupower_cpu_info.model) {
+       case 0x2A: /* SNB */
+       case 0x2D: /* SNB Xeon */
+       case 0x3A: /* IVB */
+       case 0x3E: /* IVB Xeon */
+               break;
+       default:
                return NULL;
+       }
 
        is_valid = calloc(cpu_count, sizeof(int));
        for (num = 0; num < SNB_CSTATE_COUNT; num++) {
index 2655ae9..ea095ab 100644 (file)
@@ -206,8 +206,10 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr)
        retval = pread(fd, msr, sizeof *msr, offset);
        close(fd);
 
-       if (retval != sizeof *msr)
+       if (retval != sizeof *msr) {
+               fprintf(stderr, "%s offset 0x%zx read failed\n", pathname, offset);
                return -1;
+       }
 
        return 0;
 }
@@ -1101,7 +1103,9 @@ void turbostat_loop()
 
 restart:
        retval = for_all_cpus(get_counters, EVEN_COUNTERS);
-       if (retval) {
+       if (retval < -1) {
+               exit(retval);
+       } else if (retval == -1) {
                re_initialize();
                goto restart;
        }
@@ -1114,7 +1118,9 @@ restart:
                }
                sleep(interval_sec);
                retval = for_all_cpus(get_counters, ODD_COUNTERS);
-               if (retval) {
+               if (retval < -1) {
+                       exit(retval);
+               } else if (retval == -1) {
                        re_initialize();
                        goto restart;
                }
@@ -1126,7 +1132,9 @@ restart:
                flush_stdout();
                sleep(interval_sec);
                retval = for_all_cpus(get_counters, EVEN_COUNTERS);
-               if (retval) {
+               if (retval < -1) {
+                       exit(retval);
+               } else if (retval == -1) {
                        re_initialize();
                        goto restart;
                }
@@ -1545,8 +1553,11 @@ void turbostat_init()
 int fork_it(char **argv)
 {
        pid_t child_pid;
+       int status;
 
-       for_all_cpus(get_counters, EVEN_COUNTERS);
+       status = for_all_cpus(get_counters, EVEN_COUNTERS);
+       if (status)
+               exit(status);
        /* clear affinity side-effect of get_counters() */
        sched_setaffinity(0, cpu_present_setsize, cpu_present_set);
        gettimeofday(&tv_even, (struct timezone *)NULL);
@@ -1556,7 +1567,6 @@ int fork_it(char **argv)
                /* child */
                execvp(argv[0], argv);
        } else {
-               int status;
 
                /* parent */
                if (child_pid == -1) {
@@ -1568,7 +1578,7 @@ int fork_it(char **argv)
                signal(SIGQUIT, SIG_IGN);
                if (waitpid(child_pid, &status, 0) == -1) {
                        perror("wait");
-                       exit(1);
+                       exit(status);
                }
        }
        /*
@@ -1585,7 +1595,7 @@ int fork_it(char **argv)
 
        fprintf(stderr, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec/1000000.0);
 
-       return 0;
+       return status;
 }
 
 void cmdline(int argc, char **argv)
@@ -1594,7 +1604,7 @@ void cmdline(int argc, char **argv)
 
        progname = argv[0];
 
-       while ((opt = getopt(argc, argv, "+pPSvisc:sC:m:M:")) != -1) {
+       while ((opt = getopt(argc, argv, "+pPSvi:sc:sC:m:M:")) != -1) {
                switch (opt) {
                case 'p':
                        show_core_only++;
index 96ce80a..2964b96 100644 (file)
@@ -1,8 +1,11 @@
-ifeq ("$(origin O)", "command line")
+ifeq ($(origin O), command line)
        dummy := $(if $(shell test -d $(O) || echo $(O)),$(error O=$(O) does not exist),)
        ABSOLUTE_O := $(shell cd $(O) ; pwd)
-       OUTPUT := $(ABSOLUTE_O)/
+       OUTPUT := $(ABSOLUTE_O)/$(if $(subdir),$(subdir)/)
        COMMAND_O := O=$(ABSOLUTE_O)
+ifeq ($(objtree),)
+       objtree := $(O)
+endif
 endif
 
 ifneq ($(OUTPUT),)
@@ -41,7 +44,16 @@ else
 NO_SUBDIR = :
 endif
 
-QUIET_SUBDIR0  = +$(MAKE) -C # space to separate -C and subdir
+#
+# Define a callable command for descending to a new directory
+#
+# Call by doing: $(call descend,directory[,target])
+#
+descend = \
+       +mkdir -p $(OUTPUT)$(1) && \
+       $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) $(2)
+
+QUIET_SUBDIR0  = +$(MAKE) $(COMMAND_O) -C # space to separate -C and subdir
 QUIET_SUBDIR1  =
 
 ifneq ($(findstring $(MAKEFLAGS),s),s)
@@ -56,5 +68,10 @@ ifndef V
                         $(MAKE) $(PRINT_DIR) -C $$subdir
        QUIET_FLEX     = @echo '   ' FLEX $@;
        QUIET_BISON    = @echo '   ' BISON $@;
+
+       descend = \
+               @echo '   ' DESCEND $(1); \
+               mkdir -p $(OUTPUT)$(1) && \
+               $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) $(2)
 endif
 endif
index b51d787..c7ba761 100755 (executable)
@@ -1740,8 +1740,10 @@ sub install {
     open(IN, "$output_config") or dodie("Can't read config file");
     while (<IN>) {
        if (/CONFIG_MODULES(=y)?/) {
-           $install_mods = 1 if (defined($1));
-           last;
+           if (defined($1)) {
+               $install_mods = 1;
+               last;
+           }
        }
     }
     close(IN);
index 4348014..85baf11 100644 (file)
@@ -1,4 +1,4 @@
-TARGETS = breakpoints kcmp mqueue vm cpu-hotplug memory-hotplug epoll
+TARGETS = breakpoints kcmp mqueue vm cpu-hotplug memory-hotplug
 
 all:
        for TARGET in $(TARGETS); do \
diff --git a/tools/testing/selftests/epoll/Makefile b/tools/testing/selftests/epoll/Makefile
deleted file mode 100644 (file)
index 19806ed..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-# Makefile for epoll selftests
-
-all: test_epoll
-%: %.c
-       gcc -pthread -g -o $@ $^
-
-run_tests: all
-       ./test_epoll
-
-clean:
-       $(RM) test_epoll
diff --git a/tools/testing/selftests/epoll/test_epoll.c b/tools/testing/selftests/epoll/test_epoll.c
deleted file mode 100644 (file)
index e0fcff1..0000000
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- *  tools/testing/selftests/epoll/test_epoll.c
- *
- *  Copyright 2012 Adobe Systems Incorporated
- *
- *  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.
- *
- *  Paton J. Lewis <palewis@adobe.com>
- *
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/epoll.h>
-#include <sys/socket.h>
-
-/*
- * A pointer to an epoll_item_private structure will be stored in the epoll
- * item's event structure so that we can get access to the epoll_item_private
- * data after calling epoll_wait:
- */
-struct epoll_item_private {
-       int index;  /* Position of this struct within the epoll_items array. */
-       int fd;
-       uint32_t events;
-       pthread_mutex_t mutex;  /* Guards the following variables... */
-       int stop;
-       int status;  /* Stores any error encountered while handling item. */
-       /* The following variable allows us to test whether we have encountered
-          a problem while attempting to cancel and delete the associated
-          event. When the test program exits, 'deleted' should be exactly
-          one. If it is greater than one, then the failed test reflects a real
-          world situation where we would have tried to access the epoll item's
-          private data after deleting it: */
-       int deleted;
-};
-
-struct epoll_item_private *epoll_items;
-
-/*
- * Delete the specified item from the epoll set. In a real-world secneario this
- * is where we would free the associated data structure, but in this testing
- * environment we retain the structure so that we can test for double-deletion:
- */
-void delete_item(int index)
-{
-       __sync_fetch_and_add(&epoll_items[index].deleted, 1);
-}
-
-/*
- * A pointer to a read_thread_data structure will be passed as the argument to
- * each read thread:
- */
-struct read_thread_data {
-       int stop;
-       int status;  /* Indicates any error encountered by the read thread. */
-       int epoll_set;
-};
-
-/*
- * The function executed by the read threads:
- */
-void *read_thread_function(void *function_data)
-{
-       struct read_thread_data *thread_data =
-               (struct read_thread_data *)function_data;
-       struct epoll_event event_data;
-       struct epoll_item_private *item_data;
-       char socket_data;
-
-       /* Handle events until we encounter an error or this thread's 'stop'
-          condition is set: */
-       while (1) {
-               int result = epoll_wait(thread_data->epoll_set,
-                                       &event_data,
-                                       1,      /* Number of desired events */
-                                       1000);  /* Timeout in ms */
-               if (result < 0) {
-                       /* Breakpoints signal all threads. Ignore that while
-                          debugging: */
-                       if (errno == EINTR)
-                               continue;
-                       thread_data->status = errno;
-                       return 0;
-               } else if (thread_data->stop)
-                       return 0;
-               else if (result == 0)  /* Timeout */
-                       continue;
-
-               /* We need the mutex here because checking for the stop
-                  condition and re-enabling the epoll item need to be done
-                  together as one atomic operation when EPOLL_CTL_DISABLE is
-                  available: */
-               item_data = (struct epoll_item_private *)event_data.data.ptr;
-               pthread_mutex_lock(&item_data->mutex);
-
-               /* Remove the item from the epoll set if we want to stop
-                  handling that event: */
-               if (item_data->stop)
-                       delete_item(item_data->index);
-               else {
-                       /* Clear the data that was written to the other end of
-                          our non-blocking socket: */
-                       do {
-                               if (read(item_data->fd, &socket_data, 1) < 1) {
-                                       if ((errno == EAGAIN) ||
-                                           (errno == EWOULDBLOCK))
-                                               break;
-                                       else
-                                               goto error_unlock;
-                               }
-                       } while (item_data->events & EPOLLET);
-
-                       /* The item was one-shot, so re-enable it: */
-                       event_data.events = item_data->events;
-                       if (epoll_ctl(thread_data->epoll_set,
-                                                 EPOLL_CTL_MOD,
-                                                 item_data->fd,
-                                                 &event_data) < 0)
-                               goto error_unlock;
-               }
-
-               pthread_mutex_unlock(&item_data->mutex);
-       }
-
-error_unlock:
-       thread_data->status = item_data->status = errno;
-       pthread_mutex_unlock(&item_data->mutex);
-       return 0;
-}
-
-/*
- * A pointer to a write_thread_data structure will be passed as the argument to
- * the write thread:
- */
-struct write_thread_data {
-       int stop;
-       int status;  /* Indicates any error encountered by the write thread. */
-       int n_fds;
-       int *fds;
-};
-
-/*
- * The function executed by the write thread. It writes a single byte to each
- * socket in turn until the stop condition for this thread is set. If writing to
- * a socket would block (i.e. errno was EAGAIN), we leave that socket alone for
- * the moment and just move on to the next socket in the list. We don't care
- * about the order in which we deliver events to the epoll set. In fact we don't
- * care about the data we're writing to the pipes at all; we just want to
- * trigger epoll events:
- */
-void *write_thread_function(void *function_data)
-{
-       const char data = 'X';
-       int index;
-       struct write_thread_data *thread_data =
-               (struct write_thread_data *)function_data;
-       while (!write_thread_data->stop)
-               for (index = 0;
-                    !thread_data->stop && (index < thread_data->n_fds);
-                    ++index)
-                       if ((write(thread_data->fds[index], &data, 1) < 1) &&
-                               (errno != EAGAIN) &&
-                               (errno != EWOULDBLOCK)) {
-                               write_thread_data->status = errno;
-                               return;
-                       }
-}
-
-/*
- * Arguments are currently ignored:
- */
-int main(int argc, char **argv)
-{
-       const int n_read_threads = 100;
-       const int n_epoll_items = 500;
-       int index;
-       int epoll_set = epoll_create1(0);
-       struct write_thread_data write_thread_data = {
-               0, 0, n_epoll_items, malloc(n_epoll_items * sizeof(int))
-       };
-       struct read_thread_data *read_thread_data =
-               malloc(n_read_threads * sizeof(struct read_thread_data));
-       pthread_t *read_threads = malloc(n_read_threads * sizeof(pthread_t));
-       pthread_t write_thread;
-
-       printf("-----------------\n");
-       printf("Runing test_epoll\n");
-       printf("-----------------\n");
-
-       epoll_items = malloc(n_epoll_items * sizeof(struct epoll_item_private));
-
-       if (epoll_set < 0 || epoll_items == 0 || write_thread_data.fds == 0 ||
-               read_thread_data == 0 || read_threads == 0)
-               goto error;
-
-       if (sysconf(_SC_NPROCESSORS_ONLN) < 2) {
-               printf("Error: please run this test on a multi-core system.\n");
-               goto error;
-       }
-
-       /* Create the socket pairs and epoll items: */
-       for (index = 0; index < n_epoll_items; ++index) {
-               int socket_pair[2];
-               struct epoll_event event_data;
-               if (socketpair(AF_UNIX,
-                              SOCK_STREAM | SOCK_NONBLOCK,
-                              0,
-                              socket_pair) < 0)
-                       goto error;
-               write_thread_data.fds[index] = socket_pair[0];
-               epoll_items[index].index = index;
-               epoll_items[index].fd = socket_pair[1];
-               if (pthread_mutex_init(&epoll_items[index].mutex, NULL) != 0)
-                       goto error;
-               /* We always use EPOLLONESHOT because this test is currently
-                  structured to demonstrate the need for EPOLL_CTL_DISABLE,
-                  which only produces useful information in the EPOLLONESHOT
-                  case (without EPOLLONESHOT, calling epoll_ctl with
-                  EPOLL_CTL_DISABLE will never return EBUSY). If support for
-                  testing events without EPOLLONESHOT is desired, it should
-                  probably be implemented in a separate unit test. */
-               epoll_items[index].events = EPOLLIN | EPOLLONESHOT;
-               if (index < n_epoll_items / 2)
-                       epoll_items[index].events |= EPOLLET;
-               epoll_items[index].stop = 0;
-               epoll_items[index].status = 0;
-               epoll_items[index].deleted = 0;
-               event_data.events = epoll_items[index].events;
-               event_data.data.ptr = &epoll_items[index];
-               if (epoll_ctl(epoll_set,
-                             EPOLL_CTL_ADD,
-                             epoll_items[index].fd,
-                             &event_data) < 0)
-                       goto error;
-       }
-
-       /* Create and start the read threads: */
-       for (index = 0; index < n_read_threads; ++index) {
-               read_thread_data[index].stop = 0;
-               read_thread_data[index].status = 0;
-               read_thread_data[index].epoll_set = epoll_set;
-               if (pthread_create(&read_threads[index],
-                                  NULL,
-                                  read_thread_function,
-                                  &read_thread_data[index]) != 0)
-                       goto error;
-       }
-
-       if (pthread_create(&write_thread,
-                          NULL,
-                          write_thread_function,
-                          &write_thread_data) != 0)
-               goto error;
-
-       /* Cancel all event pollers: */
-#ifdef EPOLL_CTL_DISABLE
-       for (index = 0; index < n_epoll_items; ++index) {
-               pthread_mutex_lock(&epoll_items[index].mutex);
-               ++epoll_items[index].stop;
-               if (epoll_ctl(epoll_set,
-                             EPOLL_CTL_DISABLE,
-                             epoll_items[index].fd,
-                             NULL) == 0)
-                       delete_item(index);
-               else if (errno != EBUSY) {
-                       pthread_mutex_unlock(&epoll_items[index].mutex);
-                       goto error;
-               }
-               /* EBUSY means events were being handled; allow the other thread
-                  to delete the item. */
-               pthread_mutex_unlock(&epoll_items[index].mutex);
-       }
-#else
-       for (index = 0; index < n_epoll_items; ++index) {
-               pthread_mutex_lock(&epoll_items[index].mutex);
-               ++epoll_items[index].stop;
-               pthread_mutex_unlock(&epoll_items[index].mutex);
-               /* Wait in case a thread running read_thread_function is
-                  currently executing code between epoll_wait and
-                  pthread_mutex_lock with this item. Note that a longer delay
-                  would make double-deletion less likely (at the expense of
-                  performance), but there is no guarantee that any delay would
-                  ever be sufficient. Note also that we delete all event
-                  pollers at once for testing purposes, but in a real-world
-                  environment we are likely to want to be able to cancel event
-                  pollers at arbitrary times. Therefore we can't improve this
-                  situation by just splitting this loop into two loops
-                  (i.e. signal 'stop' for all items, sleep, and then delete all
-                  items). We also can't fix the problem via EPOLL_CTL_DEL
-                  because that command can't prevent the case where some other
-                  thread is executing read_thread_function within the region
-                  mentioned above: */
-               usleep(1);
-               pthread_mutex_lock(&epoll_items[index].mutex);
-               if (!epoll_items[index].deleted)
-                       delete_item(index);
-               pthread_mutex_unlock(&epoll_items[index].mutex);
-       }
-#endif
-
-       /* Shut down the read threads: */
-       for (index = 0; index < n_read_threads; ++index)
-               __sync_fetch_and_add(&read_thread_data[index].stop, 1);
-       for (index = 0; index < n_read_threads; ++index) {
-               if (pthread_join(read_threads[index], NULL) != 0)
-                       goto error;
-               if (read_thread_data[index].status)
-                       goto error;
-       }
-
-       /* Shut down the write thread: */
-       __sync_fetch_and_add(&write_thread_data.stop, 1);
-       if ((pthread_join(write_thread, NULL) != 0) || write_thread_data.status)
-               goto error;
-
-       /* Check for final error conditions: */
-       for (index = 0; index < n_epoll_items; ++index) {
-               if (epoll_items[index].status != 0)
-                       goto error;
-               if (pthread_mutex_destroy(&epoll_items[index].mutex) < 0)
-                       goto error;
-       }
-       for (index = 0; index < n_epoll_items; ++index)
-               if (epoll_items[index].deleted != 1) {
-                       printf("Error: item data deleted %1d times.\n",
-                                  epoll_items[index].deleted);
-                       goto error;
-               }
-
-       printf("[PASS]\n");
-       return 0;
-
- error:
-       printf("[FAIL]\n");
-       return errno;
-}
index cd1b03e..b76edf2 100644 (file)
@@ -35,7 +35,7 @@
 #include <sys/mount.h>
 #include <sys/statfs.h>
 #include "../../include/uapi/linux/magic.h"
-#include "../../include/linux/kernel-page-flags.h"
+#include "../../include/uapi/linux/kernel-page-flags.h"
 
 
 #ifndef MAX_PATH
index af0f22f..aca6edc 100644 (file)
@@ -303,7 +303,7 @@ static int cpio_mkfile(const char *name, const char *location,
        int retval;
        int rc = -1;
        int namesize;
-       int i;
+       unsigned int i;
 
        mode |= S_IFREG;
 
@@ -381,25 +381,28 @@ error:
 
 static char *cpio_replace_env(char *new_location)
 {
-       char expanded[PATH_MAX + 1];
-       char env_var[PATH_MAX + 1];
-       char *start;
-       char *end;
-
-       for (start = NULL; (start = strstr(new_location, "${")); ) {
-               end = strchr(start, '}');
-               if (start < end) {
-                       *env_var = *expanded = '\0';
-                       strncat(env_var, start + 2, end - start - 2);
-                       strncat(expanded, new_location, start - new_location);
-                       strncat(expanded, getenv(env_var), PATH_MAX);
-                       strncat(expanded, end + 1, PATH_MAX);
-                       strncpy(new_location, expanded, PATH_MAX);
-               } else
-                       break;
-       }
-
-       return new_location;
+       char expanded[PATH_MAX + 1];
+       char env_var[PATH_MAX + 1];
+       char *start;
+       char *end;
+
+       for (start = NULL; (start = strstr(new_location, "${")); ) {
+               end = strchr(start, '}');
+               if (start < end) {
+                       *env_var = *expanded = '\0';
+                       strncat(env_var, start + 2, end - start - 2);
+                       strncat(expanded, new_location, start - new_location);
+                       strncat(expanded, getenv(env_var),
+                               PATH_MAX - strlen(expanded));
+                       strncat(expanded, end + 1,
+                               PATH_MAX - strlen(expanded));
+                       strncpy(new_location, expanded, PATH_MAX);
+                       new_location[PATH_MAX] = 0;
+               } else
+                       break;
+       }
+
+       return new_location;
 }
 
 
index e59bb63..be70035 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);